21#include "llvm/IR/IntrinsicsRISCV.h"
43 if (!Subtarget.useRVVForFixedLengthVectors())
47 if (FVTy->getNumElements() < 2)
57 return Factor * LMUL <= 8;
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};
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};
73 Intrinsic::riscv_vlsseg2_mask, Intrinsic::riscv_vlsseg3_mask,
74 Intrinsic::riscv_vlsseg4_mask, Intrinsic::riscv_vlsseg5_mask,
75 Intrinsic::riscv_vlsseg6_mask, Intrinsic::riscv_vlsseg7_mask,
76 Intrinsic::riscv_vlsseg8_mask};
79 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
80 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
81 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
82 Intrinsic::riscv_vlseg8_mask};
85 Intrinsic::riscv_seg2_store_mask, Intrinsic::riscv_seg3_store_mask,
86 Intrinsic::riscv_seg4_store_mask, Intrinsic::riscv_seg5_store_mask,
87 Intrinsic::riscv_seg6_store_mask, Intrinsic::riscv_seg7_store_mask,
88 Intrinsic::riscv_seg8_store_mask};
91 Intrinsic::riscv_sseg2_store_mask, Intrinsic::riscv_sseg3_store_mask,
92 Intrinsic::riscv_sseg4_store_mask, Intrinsic::riscv_sseg5_store_mask,
93 Intrinsic::riscv_sseg6_store_mask, Intrinsic::riscv_sseg7_store_mask,
94 Intrinsic::riscv_sseg8_store_mask};
97 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
98 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
99 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
100 Intrinsic::riscv_vsseg8_mask};
134 Ptr = LI->getPointerOperand();
135 Alignment = LI->getAlign();
136 assert(!Mask &&
"Unexpected mask on a load");
137 Mask = Builder.getAllOnesMask(EC);
144 Ptr =
SI->getPointerOperand();
145 Alignment =
SI->getAlign();
146 assert(!Mask &&
"Unexpected mask on a store");
147 Mask = Builder.getAllOnesMask(EC);
154 switch (
II->getIntrinsicID()) {
157 case Intrinsic::vp_load:
158 case Intrinsic::vp_store: {
160 Ptr = VPLdSt->getMemoryPointerParam();
161 Alignment = VPLdSt->getPointerAlignment().value_or(
162 DL.getABITypeAlign(VTy->getElementType()));
164 assert(Mask &&
"vp.load and vp.store needs a mask!");
166 Value *WideEVL = VPLdSt->getVectorLengthParam();
172 auto *FactorC = ConstantInt::get(WideEVL->
getType(), Factor);
173 VL = Builder.CreateZExt(Builder.CreateExactUDiv(WideEVL, FactorC), XLenTy);
176 case Intrinsic::masked_load: {
177 Ptr =
II->getOperand(0);
178 Alignment =
II->getParamAlign(0).valueOrOne();
183 assert(Mask &&
"masked.load needs a mask!");
186 ? Builder.CreateElementCount(XLenTy, VTy->getElementCount())
190 case Intrinsic::masked_store: {
191 Ptr =
II->getOperand(1);
192 Alignment =
II->getParamAlign(1).valueOrOne();
194 assert(Mask &&
"masked.store needs a mask!");
197 ? Builder.CreateElementCount(XLenTy, VTy->getElementCount())
227 unsigned MaskFactor = GapMask.
popcount();
230 auto *XLenTy = Builder.getIntNTy(Subtarget.getXLen());
234 if (!
getMemOperands(MaskFactor, VTy, XLenTy, Load, Ptr, Mask, VL, Alignment))
243 if (MaskFactor < Factor && MaskFactor != 1) {
245 unsigned ScalarSizeInBytes =
DL.getTypeStoreSize(VTy->getElementType());
246 Value *Stride = ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes);
248 {VTy, PtrTy, XLenTy, XLenTy},
249 {Ptr, Stride, Mask, VL});
253 {VTy, PtrTy, XLenTy}, {Ptr, Mask, VL});
256 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
257 unsigned FactorIdx = Indices[i];
258 if (FactorIdx >= MaskFactor) {
262 Value *SubVec = Builder.CreateExtractValue(SegLoad, FactorIdx);
263 Shuffles[i]->replaceAllUsesWith(SubVec);
290 const APInt &GapMask)
const {
295 unsigned MaskFactor = GapMask.
popcount();
296 if (MaskFactor < 2 || !GapMask.
isMask())
305 ShuffleVTy->getNumElements() / Factor);
306 auto *XLenTy = Builder.getIntNTy(Subtarget.getXLen());
310 if (!
getMemOperands(MaskFactor, VTy, XLenTy, Store, Ptr, LaneMask, VL,
320 if (MaskFactor < Factor)
324 {VTy, PtrTy, XLenTy, XLenTy});
329 {VTy, PtrTy, XLenTy});
334 for (
unsigned i = 0; i < MaskFactor; i++) {
336 for (
unsigned j = 0; j < VTy->getNumElements(); j++)
337 NewShuffleMask.
push_back(Mask[i + Factor * j]);
339 Value *Shuffle = Builder.CreateShuffleVector(
341 Ops.push_back(Shuffle);
343 NewShuffleMask.
clear();
346 if (MaskFactor < Factor) {
348 unsigned ScalarSizeInBytes =
DL.getTypeStoreSize(VTy->getElementType());
349 Ops.push_back(ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes));
351 Ops.append({LaneMask, VL});
352 Builder.CreateCall(SegStoreFunc,
Ops);
359 const APInt &GapMask)
const {
376 bool UseStridedSeg = MaskFactor < Factor && MaskFactor > 1;
378 auto *XLenTy = Builder.getIntNTy(Subtarget.getXLen());
382 if (!
getMemOperands(Factor, ResVTy, XLenTy, Load, Ptr, Mask, VL, Alignment))
390 unsigned ElementSizeInBytes =
DL.getTypeStoreSize(ResVTy->
getElementType());
396 Value *Stride = ConstantInt::get(XLenTy, Factor * ElementSizeInBytes);
398 {ResVTy, PtrTy, XLenTy, XLenTy},
399 {Ptr, Stride, Mask, VL});
403 {ResVTy, PtrTy, XLenTy}, {Ptr, Mask, VL});
406 if (MaskFactor != Factor) {
410 for (
unsigned I = 0;
I < MaskFactor; ++
I) {
411 Value *SubVec = Builder.CreateExtractValue(SegLoad,
I);
412 Return = Builder.CreateInsertValue(Return, SubVec,
I);
421 Load->getContext(),
"riscv.vector.tuple",
423 UseStridedSeg ? MaskFactor : Factor);
429 {VecTupTy, PtrTy, XLenTy, Mask->getType()});
433 {VecTupTy, PtrTy, Mask->getType(), VL->getType()});
441 ConstantInt::get(XLenTy,
443 ConstantInt::get(XLenTy,
Log2_64(SEW))};
445 Value *Stride = ConstantInt::get(XLenTy, Factor * ElementSizeInBytes);
446 Operands.
insert(std::next(Operands.
begin(), 2), Stride);
449 CallInst *Vlseg = Builder.CreateCall(SegLoadFunc, Operands);
453 for (
unsigned i = 0; i < MaskFactor; ++i) {
454 Value *VecExtract = Builder.CreateIntrinsic(
455 Intrinsic::riscv_tuple_extract, {ResVTy, VecTupTy},
456 {Vlseg, Builder.getInt32(i)});
457 Return = Builder.CreateInsertValue(Return, VecExtract, i);
467 unsigned Factor = InterleaveValues.
size();
479 if (!
getMemOperands(Factor, InVTy, XLenTy, Store, Ptr, Mask, VL, Alignment))
489 {InVTy, PtrTy, XLenTy});
491 Ops.append({Ptr, Mask, VL});
492 Builder.CreateCall(VssegNFunc,
Ops);
495 unsigned SEW =
DL.getTypeSizeInBits(InVTy->getElementType());
496 unsigned NumElts = InVTy->getElementCount().getKnownMinValue();
498 Store->getContext(),
"riscv.vector.tuple",
502 for (
unsigned i = 0; i < Factor; ++i)
503 StoredVal = Builder.CreateIntrinsic(
504 Intrinsic::riscv_tuple_insert, {VecTupTy, InVTy},
505 {StoredVal, InterleaveValues[i], Builder.getInt32(i)});
509 {VecTupTy, PtrTy, Mask->getType(), VL->getType()});
511 Value *Operands[] = {StoredVal, Ptr, Mask, VL,
512 ConstantInt::get(XLenTy,
Log2_64(SEW))};
513 Builder.CreateCall(VssegNFunc, Operands);
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[]
static bool isMultipleOfN(const Value *V, const DataLayout &DL, unsigned N)
static const Intrinsic::ID ScalableVlsegIntrIds[]
static const Intrinsic::ID ScalableVssegIntrIds[]
static const Intrinsic::ID FixedVlssegIntrIds[]
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.
static const Intrinsic::ID FixedVsssegIntrIds[]
static const Intrinsic::ID FixedVssegIntrIds[]
static const Intrinsic::ID ScalableVlssegIntrIds[]
static SymbolRef::Type getType(const Symbol *Sym)
Class for arbitrary precision integers.
unsigned popcount() const
Count the number of bits set.
unsigned getActiveBits() const
Compute the number of active bits in the value.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isMask(unsigned numBits) const
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
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 lowerInterleavedStore(Instruction *Store, Value *Mask, ShuffleVectorInst *SVI, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved store into a vssegN intrinsic.
MVT getContainerForFixedLengthVector(MVT VT) const
bool lowerDeinterleaveIntrinsicToLoad(Instruction *Load, Value *Mask, IntrinsicInst *DI, const APInt &GapMask) const override
Lower a deinterleave intrinsic to a target specific load intrinsic.
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.
bool lowerInterleaveIntrinsicToStore(Instruction *Store, Value *Mask, ArrayRef< Value * > InterleaveValues) const override
Lower an interleave intrinsic to a target specific store intrinsic.
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.
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.
iterator insert(iterator I, T &&Elt)
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 * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
bool match(Val *V, const Pattern &P)
auto m_Value()
Match an arbitrary value and ignore it.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Mul, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWMul(const LHS &L, const RHS &R)
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
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<X> - 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<X> - 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<X> - 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.