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_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};
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};
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};
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};
128 Ptr = LI->getPointerOperand();
129 Alignment = LI->getAlign();
130 assert(!Mask &&
"Unexpected mask on a load");
131 Mask = Builder.getAllOnesMask(EC);
138 Ptr =
SI->getPointerOperand();
139 Alignment =
SI->getAlign();
140 assert(!Mask &&
"Unexpected mask on a store");
141 Mask = Builder.getAllOnesMask(EC);
148 switch (
II->getIntrinsicID()) {
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()));
158 assert(Mask &&
"vp.load and vp.store needs a mask!");
160 Value *WideEVL = VPLdSt->getVectorLengthParam();
166 auto *FactorC = ConstantInt::get(WideEVL->
getType(), Factor);
167 VL = Builder.CreateZExt(Builder.CreateExactUDiv(WideEVL, FactorC), XLenTy);
170 case Intrinsic::masked_load: {
171 Ptr =
II->getOperand(0);
177 assert(Mask &&
"masked.load needs a mask!");
180 ? Builder.CreateElementCount(XLenTy, VTy->getElementCount())
184 case Intrinsic::masked_store: {
185 Ptr =
II->getOperand(1);
188 assert(Mask &&
"masked.store needs a mask!");
191 ? Builder.CreateElementCount(XLenTy, VTy->getElementCount())
218 unsigned MaskFactor = GapMask.
popcount();
219 if (MaskFactor < 2 || !GapMask.
isMask())
225 auto *XLenTy = Builder.getIntNTy(Subtarget.getXLen());
238 if (MaskFactor < Factor) {
240 unsigned ScalarSizeInBytes =
DL.getTypeStoreSize(VTy->getElementType());
241 Value *Stride = ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes);
243 {VTy, PtrTy, XLenTy, XLenTy},
244 {
Ptr, Stride, Mask, VL});
248 {VTy, PtrTy, XLenTy}, {
Ptr, Mask, VL});
251 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
252 unsigned FactorIdx = Indices[i];
253 if (FactorIdx >= MaskFactor) {
257 Value *SubVec = Builder.CreateExtractValue(SegLoad, FactorIdx);
258 Shuffles[i]->replaceAllUsesWith(SubVec);
285 const APInt &GapMask)
const {
290 unsigned MaskFactor = GapMask.
popcount();
291 if (MaskFactor < 2 || !GapMask.
isMask())
300 ShuffleVTy->getNumElements() / Factor);
301 auto *XLenTy = Builder.getIntNTy(Subtarget.getXLen());
315 if (MaskFactor < Factor)
319 {VTy, PtrTy, XLenTy, XLenTy});
324 {VTy, PtrTy, XLenTy});
329 for (
unsigned i = 0; i < MaskFactor; i++) {
331 for (
unsigned j = 0; j < VTy->getNumElements(); j++)
332 NewShuffleMask.
push_back(Mask[i + Factor * j]);
334 Value *Shuffle = Builder.CreateShuffleVector(
336 Ops.push_back(Shuffle);
338 NewShuffleMask.
clear();
341 if (MaskFactor < Factor) {
343 unsigned ScalarSizeInBytes =
DL.getTypeStoreSize(VTy->getElementType());
344 Ops.push_back(ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes));
346 Ops.append({LaneMask, VL});
347 Builder.CreateCall(SegStoreFunc,
Ops);
363 auto *XLenTy = Builder.getIntNTy(Subtarget.getXLen());
378 {ResVTy, PtrTy, XLenTy}, {
Ptr, Mask, VL});
383 Load->getContext(),
"riscv.vector.tuple",
388 {VecTupTy, PtrTy, Mask->getType(), VL->getType()});
395 ConstantInt::get(XLenTy,
397 ConstantInt::get(XLenTy,
Log2_64(SEW))};
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);
417 unsigned Factor = InterleaveValues.
size();
432 unsigned AS =
Ptr->getType()->getPointerAddressSpace();
439 {InVTy, PtrTy, XLenTy});
441 Ops.append({
Ptr, Mask, VL});
442 Builder.CreateCall(VssegNFunc,
Ops);
445 unsigned SEW =
DL.getTypeSizeInBits(InVTy->getElementType());
446 unsigned NumElts = InVTy->getElementCount().getKnownMinValue();
448 Store->getContext(),
"riscv.vector.tuple",
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)});
459 {VecTupTy, PtrTy, Mask->getType(), VL->getType()});
462 ConstantInt::get(XLenTy,
Log2_64(SEW))};
463 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[]
mir Rename Register Operands
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 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.
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 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.
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<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.