21#include "llvm/IR/IntrinsicsRISCV.h"
42 if (
auto *FVTy = dyn_cast<FixedVectorType>(VTy)) {
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};
101 using namespace PatternMatch;
126 if (
auto *LI = dyn_cast<LoadInst>(
I)) {
128 Ptr = LI->getPointerOperand();
129 Alignment = LI->getAlign();
130 assert(!Mask &&
"Unexpected mask on a load");
136 if (
auto *SI = dyn_cast<StoreInst>(
I)) {
138 Ptr = SI->getPointerOperand();
139 Alignment = SI->getAlign();
140 assert(!Mask &&
"Unexpected mask on a store");
147 auto *
II = cast<IntrinsicInst>(
I);
148 switch (
II->getIntrinsicID()) {
151 case Intrinsic::vp_load:
152 case Intrinsic::vp_store: {
153 auto *VPLdSt = cast<VPIntrinsic>(
I);
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);
170 case Intrinsic::masked_load: {
171 Ptr =
II->getOperand(0);
172 Alignment = cast<ConstantInt>(
II->getArgOperand(1))->getAlignValue();
174 if (!isa<UndefValue>(
II->getOperand(3)))
177 assert(Mask &&
"masked.load needs a mask!");
179 VL = isa<FixedVectorType>(VTy)
184 case Intrinsic::masked_store: {
185 Ptr =
II->getOperand(1);
186 Alignment = cast<ConstantInt>(
II->getArgOperand(2))->getAlignValue();
188 assert(Mask &&
"masked.store needs a mask!");
190 VL = isa<FixedVectorType>(VTy)
218 unsigned MaskFactor = GapMask.
popcount();
219 if (MaskFactor < 2 || !GapMask.
isMask())
224 auto *VTy = cast<FixedVectorType>(Shuffles[0]->
getType());
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) {
258 Shuffles[i]->replaceAllUsesWith(SubVec);
285 const APInt &GapMask)
const {
290 unsigned MaskFactor = GapMask.
popcount();
291 if (MaskFactor < 2 || !GapMask.
isMask())
297 auto *ShuffleVTy = cast<FixedVectorType>(SVI->
getType());
300 ShuffleVTy->getNumElements() / Factor);
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]);
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});
376 if (isa<FixedVectorType>(ResVTy)) {
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) {
405 Intrinsic::riscv_tuple_extract, {ResVTy, VecTupTy},
417 unsigned Factor = InterleaveValues.
size();
423 auto *InVTy = cast<VectorType>(InterleaveValues[0]->
getType());
432 unsigned AS =
Ptr->getType()->getPointerAddressSpace();
436 if (isa<FixedVectorType>(InVTy)) {
439 {InVTy, PtrTy, XLenTy});
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)
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))};
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.
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)
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * getAllOnesMask(ElementCount NumElts)
Return an all true boolean vector (mask) with NumElts lanes.
LLVM_ABI CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
Value * CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name="")
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
LLVM_ABI Value * CreateElementCount(Type *Ty, ElementCount EC)
Create an expression which evaluates to the number of elements in EC at runtime.
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 useRVVForFixedLengthVectors() const
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 append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
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.
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.
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.
LLVM_ABI VectorType * getDeinterleavedVectorType(IntrinsicInst *DI)
Given a deinterleaveN intrinsic, return the (narrow) vector type of each factor.
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.