33#define DEBUG_TYPE "vectorutils"
45 case Intrinsic::bswap:
46 case Intrinsic::bitreverse:
47 case Intrinsic::ctpop:
56 case Intrinsic::sadd_sat:
57 case Intrinsic::ssub_sat:
58 case Intrinsic::uadd_sat:
59 case Intrinsic::usub_sat:
60 case Intrinsic::smul_fix:
61 case Intrinsic::smul_fix_sat:
62 case Intrinsic::umul_fix:
63 case Intrinsic::umul_fix_sat:
64 case Intrinsic::uadd_with_overflow:
65 case Intrinsic::sadd_with_overflow:
66 case Intrinsic::usub_with_overflow:
67 case Intrinsic::ssub_with_overflow:
68 case Intrinsic::umul_with_overflow:
69 case Intrinsic::smul_with_overflow:
74 case Intrinsic::atan2:
77 case Intrinsic::sincos:
78 case Intrinsic::sincospi:
84 case Intrinsic::exp10:
86 case Intrinsic::frexp:
87 case Intrinsic::ldexp:
89 case Intrinsic::log10:
92 case Intrinsic::minnum:
93 case Intrinsic::maxnum:
94 case Intrinsic::minimum:
95 case Intrinsic::maximum:
96 case Intrinsic::minimumnum:
97 case Intrinsic::maximumnum:
99 case Intrinsic::copysign:
100 case Intrinsic::floor:
101 case Intrinsic::ceil:
102 case Intrinsic::trunc:
103 case Intrinsic::rint:
104 case Intrinsic::nearbyint:
105 case Intrinsic::round:
106 case Intrinsic::roundeven:
109 case Intrinsic::fmuladd:
110 case Intrinsic::is_fpclass:
111 case Intrinsic::powi:
112 case Intrinsic::canonicalize:
113 case Intrinsic::fptosi_sat:
114 case Intrinsic::fptoui_sat:
115 case Intrinsic::lround:
116 case Intrinsic::llround:
117 case Intrinsic::lrint:
118 case Intrinsic::llrint:
119 case Intrinsic::ucmp:
120 case Intrinsic::scmp:
121 case Intrinsic::clmul:
122 case Intrinsic::pdep:
123 case Intrinsic::pext:
124 case Intrinsic::smulh:
125 case Intrinsic::umulh:
141 unsigned ScalarOpdIdx,
145 return TTI->isTargetIntrinsicWithScalarOpAtArg(ID, ScalarOpdIdx);
153 case Intrinsic::ctlz:
154 case Intrinsic::cttz:
155 case Intrinsic::is_fpclass:
156 case Intrinsic::powi:
157 case Intrinsic::vector_extract:
158 case Intrinsic::masked_compressstore:
159 return (ScalarOpdIdx == 1);
160 case Intrinsic::smul_fix:
161 case Intrinsic::smul_fix_sat:
162 case Intrinsic::umul_fix:
163 case Intrinsic::umul_fix_sat:
164 case Intrinsic::vector_splice_left:
165 case Intrinsic::vector_splice_right:
166 return (ScalarOpdIdx == 2);
167 case Intrinsic::experimental_vp_splice:
168 return ScalarOpdIdx == 2 || ScalarOpdIdx == 4;
169 case Intrinsic::experimental_vp_strided_load:
170 return ScalarOpdIdx == 0 || ScalarOpdIdx == 1;
171 case Intrinsic::experimental_vp_strided_store:
172 return ScalarOpdIdx == 1 || ScalarOpdIdx == 2;
173 case Intrinsic::masked_expandload:
174 return ScalarOpdIdx == 0;
175 case Intrinsic::loop_dependence_war_mask:
187 return TTI->isTargetIntrinsicWithOverloadTypeAtArg(ID, OpdIdx);
190 case Intrinsic::fptosi_sat:
191 case Intrinsic::fptoui_sat:
192 case Intrinsic::lround:
193 case Intrinsic::llround:
194 case Intrinsic::lrint:
195 case Intrinsic::llrint:
196 case Intrinsic::ucmp:
197 case Intrinsic::scmp:
198 case Intrinsic::vector_extract:
199 case Intrinsic::loop_dependence_war_mask:
200 case Intrinsic::masked_expandload:
201 return OpdIdx == -1 || OpdIdx == 0;
202 case Intrinsic::modf:
203 case Intrinsic::sincos:
204 case Intrinsic::sincospi:
205 case Intrinsic::is_fpclass:
207 case Intrinsic::powi:
208 case Intrinsic::ldexp:
209 return OpdIdx == -1 || OpdIdx == 1;
210 case Intrinsic::experimental_vp_strided_load:
211 return OpdIdx == -1 || OpdIdx == 0 || OpdIdx == 1;
212 case Intrinsic::experimental_vp_strided_store:
213 return OpdIdx == 0 || OpdIdx == 1 || OpdIdx == 2;
214 case Intrinsic::masked_compressstore:
215 return OpdIdx == 0 || OpdIdx == 1;
221std::optional<unsigned>
224 case Intrinsic::experimental_vp_strided_store:
225 case Intrinsic::masked_compressstore:
227 case Intrinsic::experimental_vp_strided_load:
228 case Intrinsic::masked_expandload:
235std::optional<unsigned>
238 case Intrinsic::experimental_vp_strided_store:
239 case Intrinsic::masked_compressstore:
250 case Intrinsic::masked_compressstore:
252 case Intrinsic::masked_expandload:
263 return TTI->isTargetIntrinsicWithStructReturnOverloadAtField(ID, RetIdx);
266 case Intrinsic::frexp:
267 return RetIdx == 0 || RetIdx == 1;
283 ID == Intrinsic::lifetime_end || ID == Intrinsic::assume ||
284 ID == Intrinsic::experimental_noalias_scope_decl ||
285 ID == Intrinsic::sideeffect || ID == Intrinsic::pseudoprobe)
299 if (HasIntrinsicMapping(Intrinsic::sincos))
301 LibFunc LF = NotLibFunc;
303 LF = LibFunc_sincosf;
306 if (LF != NotLibFunc &&
TLI.isFunctionVectorizable(
TLI.getName(LF), EC))
308 return HasIntrinsicMapping(Intrinsic::sin) &&
309 HasIntrinsicMapping(Intrinsic::cos);
314 case Intrinsic::vector_interleave2:
316 case Intrinsic::vector_interleave3:
318 case Intrinsic::vector_interleave4:
320 case Intrinsic::vector_interleave5:
322 case Intrinsic::vector_interleave6:
324 case Intrinsic::vector_interleave7:
326 case Intrinsic::vector_interleave8:
335 case Intrinsic::vector_deinterleave2:
337 case Intrinsic::vector_deinterleave3:
339 case Intrinsic::vector_deinterleave4:
341 case Intrinsic::vector_deinterleave5:
343 case Intrinsic::vector_deinterleave6:
345 case Intrinsic::vector_deinterleave7:
347 case Intrinsic::vector_deinterleave8:
355 [[maybe_unused]]
unsigned Factor =
358 assert(Factor && Factor == DISubtypes.
size() &&
359 "unexpected deinterleave factor or result type");
367 assert(V->getType()->isVectorTy() &&
"Not looking at a vector?");
371 unsigned Width = FVTy->getNumElements();
377 return C->getAggregateElement(EltNo);
388 return III->getOperand(1);
391 if (III == III->getOperand(0))
407 if (InEl < (
int)LHSWidth)
416 if (
Constant *Elt =
C->getAggregateElement(EltNo))
417 if (Elt->isNullValue())
423 if (EltNo < VTy->getElementCount().getKnownMinValue())
438 if (SplatIndex != -1 && SplatIndex != M)
444 assert((SplatIndex == -1 || SplatIndex >= 0) &&
"Negative index?");
455 return C->getSplatValue();
476 return C->getSplatValue() !=
nullptr;
491 return Shuf->getMaskValue(Index) == Index;
514 const APInt &DemandedElts,
APInt &DemandedLHS,
515 APInt &DemandedRHS,
bool AllowUndefElts) {
519 if (DemandedElts.
isZero())
528 for (
unsigned I = 0, E = Mask.size();
I != E; ++
I) {
530 assert((-1 <= M) && (M < (SrcWidth * 2)) &&
531 "Invalid shuffle mask constant");
533 if (!DemandedElts[
I] || (AllowUndefElts && (M < 0)))
544 DemandedRHS.
setBit(M - SrcWidth);
551 std::array<std::pair<int, int>, 2> &SrcInfo) {
552 const int SignalValue = NumElts * 2;
553 SrcInfo[0] = {-1, SignalValue};
554 SrcInfo[1] = {-1, SignalValue};
558 int Src = M >= NumElts;
559 int Diff = (int)i - (M % NumElts);
561 for (
int j = 0; j < 2; j++) {
562 auto &[SrcE, DiffE] = SrcInfo[j];
564 assert(DiffE == SignalValue);
568 if (SrcE == Src && DiffE == Diff) {
577 return SrcInfo[0].first != -1;
582 assert(Scale > 0 &&
"Unexpected scaling factor");
586 ScaledMask.
assign(Mask.begin(), Mask.end());
591 for (
int MaskElt : Mask) {
593 assert(((uint64_t)Scale * MaskElt + (Scale - 1)) <= INT32_MAX &&
594 "Overflowed 32-bits");
596 for (
int SliceElt = 0; SliceElt != Scale; ++SliceElt)
597 ScaledMask.
push_back(MaskElt < 0 ? MaskElt : Scale * MaskElt + SliceElt);
603 assert(Scale > 0 &&
"Unexpected scaling factor");
607 ScaledMask.
assign(Mask.begin(), Mask.end());
612 int NumElts = Mask.size();
613 if (NumElts % Scale != 0)
617 ScaledMask.
reserve(NumElts / Scale);
622 assert((
int)MaskSlice.
size() == Scale &&
"Expected Scale-sized slice.");
625 int SliceFront = MaskSlice.
front();
626 if (SliceFront < 0) {
634 if (SliceFront % Scale != 0)
637 for (
int i = 1; i < Scale; ++i)
638 if (MaskSlice[i] != SliceFront + i)
640 ScaledMask.
push_back(SliceFront / Scale);
642 Mask = Mask.drop_front(Scale);
643 }
while (!Mask.empty());
645 assert((
int)ScaledMask.
size() * Scale == NumElts &&
"Unexpected scaled mask");
654 unsigned NumElts = M.size();
655 if (NumElts % 2 != 0)
659 for (
unsigned i = 0; i < NumElts; i += 2) {
664 if (
M0 == -1 &&
M1 == -1) {
669 if (
M0 == -1 &&
M1 != -1 && (
M1 % 2) == 1) {
674 if (
M0 != -1 && (
M0 % 2) == 0 && ((
M0 + 1) ==
M1 ||
M1 == -1)) {
683 assert(NewMask.
size() == NumElts / 2 &&
"Incorrect size for mask!");
689 unsigned NumSrcElts = Mask.size();
690 assert(NumSrcElts > 0 && NumDstElts > 0 &&
"Unexpected scaling factor");
693 if (NumSrcElts == NumDstElts) {
694 ScaledMask.
assign(Mask.begin(), Mask.end());
699 assert(((NumSrcElts % NumDstElts) == 0 || (NumDstElts % NumSrcElts) == 0) &&
700 "Unexpected scaling factor");
702 if (NumSrcElts > NumDstElts) {
703 int Scale = NumSrcElts / NumDstElts;
707 int Scale = NumDstElts / NumSrcElts;
714 std::array<SmallVector<int, 16>, 2> TmpMasks;
717 for (
unsigned Scale = 2; Scale <= InputMask.
size(); ++Scale) {
727 ArrayRef<int> Mask,
unsigned NumOfSrcRegs,
unsigned NumOfDestRegs,
728 unsigned NumOfUsedRegs,
function_ref<
void()> NoInputAction,
737 int Sz = Mask.size();
738 unsigned SzDest = Sz / NumOfDestRegs;
739 unsigned SzSrc = Sz / NumOfSrcRegs;
740 for (
unsigned I = 0;
I < NumOfDestRegs; ++
I) {
741 auto &RegMasks = Res[
I];
742 RegMasks.
assign(2 * NumOfSrcRegs, {});
745 for (
unsigned K = 0;
K < SzDest; ++
K) {
746 int Idx =
I * SzDest +
K;
751 int MaskIdx = Mask[Idx] % Sz;
752 int SrcRegIdx = MaskIdx / SzSrc + (Mask[Idx] >= Sz ? NumOfSrcRegs : 0);
755 if (RegMasks[SrcRegIdx].empty())
757 RegMasks[SrcRegIdx][
K] = MaskIdx % SzSrc;
765 switch (NumSrcRegs) {
774 unsigned SrcReg = std::distance(Dest.begin(), It);
775 SingleInputAction(*It, SrcReg,
I);
787 for (
int Idx = 0, VF = FirstMask.
size(); Idx < VF; ++Idx) {
790 "Expected undefined mask element.");
791 FirstMask[Idx] = SecondMask[Idx] + VF;
796 for (
int Idx = 0, VF = Mask.size(); Idx < VF; ++Idx) {
812 if (FirstIdx == SecondIdx) {
818 SecondMask = RegMask;
819 CombineMasks(FirstMask, SecondMask);
820 ManyInputsAction(FirstMask, FirstIdx, SecondIdx, NewReg);
822 NormalizeMask(FirstMask);
824 SecondMask = FirstMask;
825 SecondIdx = FirstIdx;
827 if (FirstIdx != SecondIdx && SecondIdx >= 0) {
828 CombineMasks(SecondMask, FirstMask);
829 ManyInputsAction(SecondMask, SecondIdx, FirstIdx, NewReg);
831 Dest[FirstIdx].clear();
832 NormalizeMask(SecondMask);
834 }
while (SecondIdx >= 0);
842 const APInt &DemandedElts,
844 APInt &DemandedRHS) {
845 assert(VectorBitWidth >= 128 &&
"Vectors smaller than 128 bit not supported");
846 int NumLanes = VectorBitWidth / 128;
848 int NumEltsPerLane = NumElts / NumLanes;
849 int HalfEltsPerLane = NumEltsPerLane / 2;
855 for (
int Idx = 0; Idx != NumElts; ++Idx) {
856 if (!DemandedElts[Idx])
858 int LaneIdx = (Idx / NumEltsPerLane) * NumEltsPerLane;
859 int LocalIdx = Idx % NumEltsPerLane;
860 if (LocalIdx < HalfEltsPerLane) {
861 DemandedLHS.
setBit(LaneIdx + 2 * LocalIdx);
863 LocalIdx -= HalfEltsPerLane;
864 DemandedRHS.
setBit(LaneIdx + 2 * LocalIdx);
885 bool SeenExtFromIllegalType =
false;
886 for (
auto *BB : Blocks)
887 for (
auto &
I : *BB) {
888 InstructionSet.insert(&
I);
891 !
TTI->isTypeLegal(
I.getOperand(0)->getType()))
892 SeenExtFromIllegalType =
true;
896 !
I.getType()->isVectorTy() &&
897 I.getOperand(0)->getType()->getScalarSizeInBits() <= 64) {
908 if (Worklist.
empty() || (
TTI && !SeenExtFromIllegalType))
912 while (!Worklist.
empty()) {
921 if (DB.getDemandedBits(
I).getBitWidth() > 64)
924 uint64_t V = DB.getDemandedBits(
I).getZExtValue();
931 !InstructionSet.count(
I))
938 !
I->getType()->isIntegerTy()) {
939 DBits[Leader] |= ~0ULL;
954 if (DBits[Leader] == ~0ULL)
958 for (
Value *O :
I->operands()) {
968 for (
auto &
I : DBits)
969 for (
auto *U :
I.first->users())
970 if (U->getType()->isIntegerTy() && DBits.
count(U) == 0)
973 for (
const auto &E : ECs) {
976 uint64_t LeaderDemandedBits = 0;
978 LeaderDemandedBits |= DBits[M];
1001 Type *Ty = M->getType();
1003 Ty =
MI->getOperand(0)->getType();
1005 if (MinBW >= Ty->getScalarSizeInBits())
1018 U.getOperandNo() == 1)
1019 return CI->uge(MinBW);
1020 return bit_ceil(DB.getDemandedBits(&U).getActiveBits()) > MinBW;
1032template <
typename ListT>
1037 List.insert(AccGroups);
1041 for (
const auto &AccGroupListOp : AccGroups->
operands()) {
1053 if (AccGroups1 == AccGroups2)
1060 if (Union.size() == 0)
1062 if (Union.size() == 1)
1074 if (!MayAccessMem1 && !MayAccessMem2)
1077 return Inst2->
getMetadata(LLVMContext::MD_access_group);
1079 return Inst1->
getMetadata(LLVMContext::MD_access_group);
1095 if (AccGroupSet2.
count(MD1))
1101 if (AccGroupSet2.
count(Item))
1106 if (Intersection.
size() == 0)
1108 if (Intersection.
size() == 1)
1121 static const unsigned SupportedIDs[] = {
1122 LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope,
1123 LLVMContext::MD_noalias, LLVMContext::MD_fpmath,
1124 LLVMContext::MD_nontemporal, LLVMContext::MD_invariant_load,
1125 LLVMContext::MD_access_group, LLVMContext::MD_mmra};
1128 for (
unsigned Idx = 0; Idx !=
Metadata.size();) {
1146 for (
auto &[Kind, MD] :
Metadata) {
1151 for (
int J = 1, E = VL.
size(); MD && J != E; ++J) {
1156 case LLVMContext::MD_mmra: {
1160 case LLVMContext::MD_tbaa:
1163 case LLVMContext::MD_alias_scope:
1166 case LLVMContext::MD_fpmath:
1169 case LLVMContext::MD_noalias:
1170 case LLVMContext::MD_nontemporal:
1171 case LLVMContext::MD_invariant_load:
1174 case LLVMContext::MD_access_group:
1199 for (
unsigned i = 0; i < VF; i++)
1200 for (
unsigned j = 0; j < Group.
getFactor(); ++j) {
1201 unsigned HasMember = Group.
getMember(j) ? 1 : 0;
1202 Mask.push_back(Builder.getInt1(HasMember));
1211 for (
unsigned i = 0; i < VF; i++)
1212 for (
unsigned j = 0; j < ReplicationFactor; j++)
1221 for (
unsigned i = 0; i < VF; i++)
1222 for (
unsigned j = 0; j < NumVecs; j++)
1223 Mask.push_back(j * VF + i);
1231 for (
unsigned i = 0; i < VF; i++)
1232 Mask.push_back(Start + i * Stride);
1239 unsigned NumUndefs) {
1241 for (
unsigned i = 0; i < NumInts; i++)
1242 Mask.push_back(Start + i);
1244 for (
unsigned i = 0; i < NumUndefs; i++)
1253 int NumEltsSigned = NumElts;
1254 assert(NumEltsSigned > 0 &&
"Expected smaller or non-zero element count");
1259 for (
int MaskElt : Mask) {
1260 assert((MaskElt < NumEltsSigned * 2) &&
"Expected valid shuffle mask");
1261 int UnaryElt = MaskElt >= NumEltsSigned ? MaskElt - NumEltsSigned : MaskElt;
1274 assert(VecTy1 && VecTy2 &&
1275 VecTy1->getScalarType() == VecTy2->getScalarType() &&
1276 "Expect two vectors with the same element type");
1280 assert(NumElts1 >= NumElts2 &&
"Unexpect the first vector has less elements");
1282 if (NumElts1 > NumElts2) {
1284 V2 = Builder.CreateShuffleVector(
1288 return Builder.CreateShuffleVector(
1294 unsigned NumVecs = Vecs.
size();
1295 assert(NumVecs > 1 &&
"Should be at least two vectors");
1301 for (
unsigned i = 0; i < NumVecs - 1; i += 2) {
1302 Value *V0 = ResList[i], *
V1 = ResList[i + 1];
1303 assert((V0->getType() ==
V1->getType() || i == NumVecs - 2) &&
1304 "Only the last vector may have a different type");
1310 if (NumVecs % 2 != 0)
1311 TmpList.
push_back(ResList[NumVecs - 1]);
1314 NumVecs = ResList.
size();
1315 }
while (NumVecs > 1);
1325 "Mask must be a vector of i1");
1339 "Mask must be a fixed width vector of i1");
1341 const unsigned VWidth =
1345 for (
unsigned i = 0; i < VWidth; i++)
1346 if (CV->getAggregateElement(i)->isNullValue())
1348 return DemandedElts;
1357 LAI(LAI), OptForSize(OptForSize) {}
1359bool InterleavedAccessInfo::isStrided(
int Stride)
const {
1360 unsigned Factor = std::abs(Stride);
1361 return Factor >= 2 && Factor <= Opts.max_interleave_group_factor;
1364void InterleavedAccessInfo::collectConstStrideAccesses(
1379 for (
auto &
I : *BB) {
1388 if (
Size * 8 !=
DL.getTypeSizeInBits(ElementTy))
1398 int64_t Stride =
getPtrStride(PSE, ElementTy, Ptr, TheLoop, *DT, Strides,
1403 AccessStrideInfo[&
I] = StrideDescriptor(Stride, Scev,
Size,
1445 bool EnablePredicatedInterleavedMemAccesses) {
1447 const auto &Strides = LAI->getSymbolicStrides();
1452 collectConstStrideAccesses(AccessStrideInfo, Strides,
1453 OptForSize ?
nullptr : &Predicates);
1455 if (AccessStrideInfo.
empty())
1459 collectDependences();
1480 for (
auto BI = AccessStrideInfo.
rbegin(), E = AccessStrideInfo.
rend();
1483 StrideDescriptor DesB = BI->second;
1489 if (isStrided(DesB.Stride) &&
1490 (!isPredicated(
B->getParent()) || EnablePredicatedInterleavedMemAccesses)) {
1495 GroupB = createInterleaveGroup(
B, DesB.Stride, DesB.Alignment);
1496 if (
B->mayWriteToMemory())
1497 StoreGroups.
insert(GroupB);
1499 LoadGroups.
insert(GroupB);
1503 for (
auto AI = std::next(BI); AI != E; ++AI) {
1505 StrideDescriptor DesA = AI->second;
1530 if (MemberOfGroupB && !canReorderMemAccessesForInterleavedGroups(
1531 A, &*AccessStrideInfo.
find(MemberOfGroupB)))
1532 return MemberOfGroupB;
1542 if (
A->mayWriteToMemory() && GroupA != GroupB) {
1550 if (GroupB && LoadGroups.
contains(GroupB))
1551 DependentInst = DependentMember(GroupB, &*AI);
1552 else if (!canReorderMemAccessesForInterleavedGroups(&*AI, &*BI))
1555 if (DependentInst) {
1560 if (GroupA && StoreGroups.
contains(GroupA)) {
1562 "dependence between "
1563 << *
A <<
" and " << *DependentInst <<
'\n');
1564 StoreGroups.
remove(GroupA);
1565 releaseGroup(GroupA);
1571 if (GroupB && LoadGroups.
contains(GroupB)) {
1573 <<
" as complete.\n");
1574 CompletedLoadGroups.
insert(GroupB);
1578 if (CompletedLoadGroups.
contains(GroupB)) {
1586 if (!isStrided(DesA.Stride) || !isStrided(DesB.Stride))
1596 (
A->mayReadFromMemory() !=
B->mayReadFromMemory()) ||
1597 (
A->mayWriteToMemory() !=
B->mayWriteToMemory()))
1602 if (DesA.Stride != DesB.Stride || DesA.Size != DesB.Size)
1612 PSE.getSE()->getMinusSCEV(DesA.Scev, DesB.Scev));
1619 if (DistanceToB %
static_cast<int64_t
>(DesB.Size))
1626 if ((isPredicated(BlockA) || isPredicated(BlockB)) &&
1627 (!EnablePredicatedInterleavedMemAccesses || BlockA != BlockB))
1633 GroupB->
getIndex(
B) + DistanceToB /
static_cast<int64_t
>(DesB.Size);
1638 <<
" into the interleave group with" << *
B
1640 InterleaveGroupMap[
A] = GroupB;
1643 if (
A->mayReadFromMemory())
1650 if (!LoadGroups.
empty() || !StoreGroups.
empty())
1651 PSE.addPredicates(Predicates);
1655 const char *FirstOrLast) ->
bool {
1657 assert(Member &&
"Group member does not exist");
1660 if (
getPtrStride(PSE, AccessTy, MemberPtr, TheLoop, *DT, Strides,
1664 LLVM_DEBUG(
dbgs() <<
"LV: Invalidate candidate interleaved group due to "
1666 <<
" group member potentially pointer-wrapping.\n");
1667 releaseGroup(Group);
1685 for (
auto *Group : LoadGroups) {
1697 if (InvalidateGroupIfMemberMayWrap(Group, 0,
"first"))
1700 InvalidateGroupIfMemberMayWrap(Group, Group->
getFactor() - 1,
"last");
1709 dbgs() <<
"LV: Invalidate candidate interleaved group due to "
1710 "a reverse access with gaps.\n");
1711 releaseGroup(Group);
1715 dbgs() <<
"LV: Interleaved group requires epilogue iteration.\n");
1716 RequiresScalarEpilogue =
true;
1720 for (
auto *Group : StoreGroups) {
1730 if (!EnablePredicatedInterleavedMemAccesses) {
1732 dbgs() <<
"LV: Invalidate candidate interleaved store group due "
1734 releaseGroup(Group);
1744 if (InvalidateGroupIfMemberMayWrap(Group, 0,
"first"))
1746 for (
int Index = Group->
getFactor() - 1; Index > 0; Index--)
1748 InvalidateGroupIfMemberMayWrap(Group, Index,
"last");
1762 bool ReleasedGroup = InterleaveGroups.
remove_if([&](
auto *Group) {
1763 if (!Group->requiresScalarEpilogue())
1767 <<
"LV: Invalidate candidate interleaved group due to gaps that "
1768 "require a scalar epilogue (not allowed under optsize) and cannot "
1769 "be masked (not enabled). \n");
1770 releaseGroupWithoutRemovingFromSet(Group);
1773 assert(ReleasedGroup &&
"At least one group must be invalidated, as a "
1774 "scalar epilogue was required");
1775 (void)ReleasedGroup;
1776 RequiresScalarEpilogue =
false;
1779template <
typename InstT>
const TargetLowering & TLI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file provides utility for Memory Model Relaxation Annotations (MMRAs).
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static SymbolRef::Type getType(const Symbol *Sym)
static Value * concatenateTwoVectors(IRBuilderBase &Builder, Value *V1, Value *V2)
A helper function for concatenating vectors.
static void addToAccessGroupList(ListT &List, MDNode *AccGroups)
Add all access groups in AccGroups to List.
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
void clearBit(unsigned BitPosition)
Set a given bit to 0.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
int64_t getSExtValue() const
Get sign extended value.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
LLVM Basic Block Representation.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this basic block belongs to.
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
This represents a collection of equivalence classes and supports three efficient operations: insert a...
iterator_range< member_iterator > members(const ECValue &ECV) const
const ElemTy & getOrInsertLeaderValue(const ElemTy &V)
Return the leader for the specified value that is in the set.
member_iterator unionSets(const ElemTy &V1, const ElemTy &V2)
Merge the two equivalence sets for the specified values, inserting them if they do not already exist ...
Common base class shared among various IRBuilders.
This instruction inserts a single (scalar) element into a VectorType value.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
void getAllMetadataOtherThanDebugLoc(SmallVectorImpl< std::pair< unsigned, MDNode * > > &MDs) const
This does the same thing as getAllMetadata, except that it filters out the debug location.
LLVM_ABI bool mayReadOrWriteMemory() const LLVM_READONLY
Return true if this instruction may read or write memory.
The group of interleaved loads/stores sharing the same stride and close to each other.
uint32_t getFactor() const
InstTy * getMember(uint32_t Index) const
Get the member with the given index Index.
bool isFull() const
Return true if this group is full, i.e. it has no gaps.
uint32_t getIndex(const InstTy *Instr) const
Get the index for the given member.
void setInsertPos(InstTy *Inst)
void addMetadata(InstTy *NewInst) const
Add metadata (e.g.
bool insertMember(InstTy *Instr, int32_t Index, Align NewAlign)
Try to insert a new member Instr with index Index and alignment NewAlign.
InterleaveGroup< Instruction > * getInterleaveGroup(const Instruction *Instr) const
Get the interleave group that Instr belongs to.
bool requiresScalarEpilogue() const
Returns true if an interleaved group that may access memory out-of-bounds requires a scalar epilogue ...
bool isInterleaved(Instruction *Instr) const
Check if Instr belongs to any interleave group.
LLVM_ABI InterleavedAccessInfo(PredicatedScalarEvolution &PSE, Loop *L, DominatorTree *DT, LoopInfo *LI, const LoopAccessInfo *LAI, bool OptForSize)
LLVM_ABI void analyzeInterleaving(bool EnableMaskedInterleavedGroup)
Analyze the interleaved accesses and collect them in interleave groups.
LLVM_ABI void invalidateGroupsRequiringScalarEpilogue()
Invalidate groups that require a scalar epilogue (due to gaps).
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
Drive the analysis of memory accesses in the loop.
BlockT * getHeader() const
Store the result of a depth first search within basic blocks contained by a single loop.
Represents a single loop in the control flow graph.
static LLVM_ABI MDNode * getMostGenericAliasScope(MDNode *A, MDNode *B)
static LLVM_ABI MDNode * getMostGenericTBAA(MDNode *A, MDNode *B)
ArrayRef< MDOperand > operands() const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI MDNode * getMostGenericFPMath(MDNode *A, MDNode *B)
unsigned getNumOperands() const
Return number of MDNode operands.
static LLVM_ABI MDNode * intersect(MDNode *A, MDNode *B)
LLVMContext & getContext() const
Tracking metadata reference owned by Metadata.
This class implements a map that also provides access to all stored values in a deterministic order.
iterator find(const KeyT &Key)
reverse_iterator rbegin()
A Module instance is used to store all the information related to an LLVM module.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
This class represents a constant integer value.
const APInt & getAPInt() const
This class represents an analyzed expression in the program.
bool remove(const value_type &X)
Remove an item from the set vector.
bool contains(const_arg_type key) const
Check if the SetVector contains the given key.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
This instruction constructs a fixed permutation of two input vectors.
int getMaskValue(unsigned Elt) const
Return the shuffle mask value of this instruction for the given element index.
VectorType * getType() const
Overload to return most specific vector type.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
bool remove_if(UnaryPredicate P)
Remove elements that match the given predicate.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
void reserve(size_type N)
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.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
ArrayRef< Type * > subtypes() const
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
static LLVM_ABI std::optional< unsigned > getMaskParamPos(Intrinsic::ID IntrinsicID)
static LLVM_ABI std::optional< unsigned > getVectorLengthParamPos(Intrinsic::ID IntrinsicID)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVMContext & getContext() const
All values hold a context through their type.
Base class of all SIMD vector types.
Type * getElementType() const
An efficient, type-erasing, non-owning reference to a callable.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI StringRef getName(ID id)
Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
LLVM_ABI bool isTriviallyScalarizable(ID id)
Returns true if the intrinsic is trivially scalarizable.
LLVM_ABI bool isTargetIntrinsic(ID IID)
isTargetIntrinsic - Returns true if IID is an intrinsic specific to a certain target.
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
AllOnesConstantMatch m_AllOnes()
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
auto m_Value()
Match an arbitrary value and ignore it.
auto m_UndefValue()
Match an arbitrary UndefValue constant.
auto m_Constant()
Match an arbitrary Constant and ignore it.
ContainsMatchingVectorElement_match< SPTy > m_ContainsMatchingVectorElement(const SPTy &SubPattern)
Match a vector constant where at least one of its elements matches the subpattern.
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
unsigned getLoadStoreAddressSpace(const Value *I)
A helper function that returns the address space of the pointer operand of load or store instruction.
LLVM_ABI Intrinsic::ID getVectorIntrinsicIDForCall(const CallInst *CI, const TargetLibraryInfo *TLI)
Returns intrinsic ID for call.
LLVM_ABI bool canInstructionHaveMMRAs(const Instruction &I)
LLVM_ABI APInt possiblyDemandedEltsInMask(Value *Mask)
Given a mask vector of the form <Y x i1>, return an APInt (of bitwidth Y) for each lane which may be ...
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
LLVM_ABI std::optional< unsigned > getVectorStoreIntrinsicDataArgIdx(Intrinsic::ID ID)
Returns the argument index of the data value of the vector store intrinsic ID, or std::nullopt if the...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
LLVM_ABI llvm::SmallVector< int, 16 > createUnaryMask(ArrayRef< int > Mask, unsigned NumElts)
Given a shuffle mask for a binary shuffle, create the equivalent shuffle mask assuming both operands ...
LLVM_ABI void getMetadataToPropagate(Instruction *Inst, SmallVectorImpl< std::pair< unsigned, MDNode * > > &Metadata)
Add metadata from Inst to Metadata, if it can be preserved after vectorization.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI const SCEV * replaceSymbolicStrideSCEV(PredicatedScalarEvolution &PSE, const Loop *Lp, const SymbolicStrideMap &PtrToStride, Value *Ptr, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Return the SCEV corresponding to a pointer with the symbolic stride replaced with constant one,...
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
Align getLoadStoreAlignment(const Value *I)
A helper function that returns the alignment of load or store instruction.
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
LLVM_ABI Instruction * propagateMetadata(Instruction *I, ArrayRef< Value * > VL)
Specifically, let Kinds = [MD_tbaa, MD_alias_scope, MD_noalias, MD_fpmath, MD_nontemporal,...
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI std::optional< int64_t > getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp, const DominatorTree &DT, const SymbolicStrideMap &StridesMap=SymbolicStrideMap(), bool ShouldCheckWrap=true, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
If the pointer has a constant stride return it in units of the access type size.
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
LLVM_ABI MDNode * intersectAccessGroups(const Instruction *Inst1, const Instruction *Inst2)
Compute the access-group list of access groups that Inst1 and Inst2 are both in.
unsigned M1(unsigned Val)
const AnalysisOptions & getAnalysisOptions(const LLVMContext &C)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool getShuffleDemandedElts(int SrcWidth, ArrayRef< int > Mask, const APInt &DemandedElts, APInt &DemandedLHS, APInt &DemandedRHS, bool AllowUndefElts=false)
Transform a shuffle mask's output demanded element mask into demanded element masks for the 2 operand...
LLVM_ABI bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)
Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...
LLVM_ABI Constant * createBitMaskForGaps(IRBuilderBase &Builder, unsigned VF, const InterleaveGroup< Instruction > &Group)
Create a mask that filters the members of an interleave group where there are gaps.
constexpr unsigned MaxAnalysisRecursionDepth
LLVM_ABI llvm::SmallVector< int, 16 > createStrideMask(unsigned Start, unsigned Stride, unsigned VF)
Create a stride shuffle mask.
LLVM_ABI void getHorizDemandedEltsForFirstOperand(unsigned VectorBitWidth, const APInt &DemandedElts, APInt &DemandedLHS, APInt &DemandedRHS)
Compute the demanded elements mask of horizontal binary operations.
LLVM_ABI llvm::SmallVector< int, 16 > createReplicatedMask(unsigned ReplicationFactor, unsigned VF)
Create a mask with replicated elements.
DenseMap< Value *, const SCEVUnknown * > SymbolicStrideMap
Maps a pointer to its symbolic (non-constant) stride.
LLVM_ABI unsigned getDeinterleaveIntrinsicFactor(Intrinsic::ID ID)
Returns the corresponding factor of llvm.vector.deinterleaveN intrinsics.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI unsigned getInterleaveIntrinsicFactor(Intrinsic::ID ID)
Returns the corresponding factor of llvm.vector.interleaveN 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...
constexpr int PoisonMaskElem
LLVM_ABI bool isTriviallyScalarizable(Intrinsic::ID ID)
Identify if the intrinsic is trivially scalarizable.
LLVM_ABI bool isValidAsAccessGroup(MDNode *AccGroup)
Return whether an MDNode might represent an access group.
LLVM_ABI Intrinsic::ID getIntrinsicForCallSite(const CallBase &CB, const TargetLibraryInfo *TLI)
Map a call instruction to an intrinsic ID.
LLVM_ABI bool isVectorIntrinsicWithStructReturnOverloadAtField(Intrinsic::ID ID, int RetIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic that returns a struct is overloaded at the struct elem...
LLVM_ABI void narrowShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Replace each shuffle mask index with the scaled sequential indices for an equivalent mask of narrowed...
LLVM_ABI bool isMaskedSlidePair(ArrayRef< int > Mask, int NumElts, std::array< std::pair< int, int >, 2 > &SrcInfo)
Does this shuffle mask represent either one slide shuffle or a pair of two slide shuffles,...
LLVM_ABI VectorType * getDeinterleavedVectorType(IntrinsicInst *DI)
Given a deinterleaveN intrinsic, return the (narrow) vector type of each factor.
LLVM_ABI llvm::SmallVector< int, 16 > createInterleaveMask(unsigned VF, unsigned NumVecs)
Create an interleave shuffle mask.
LLVM_ABI std::optional< unsigned > getVectorMemoryIntrinsicPointerArgIdx(Intrinsic::ID ID)
Returns the argument index of the pointer parameter for the vector memory intrinsic ID,...
LLVM_ABI bool isVectorIntrinsicWithScalarOpAtArg(Intrinsic::ID ID, unsigned ScalarOpdIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic has a scalar operand.
LLVM_ABI Value * findScalarElement(Value *V, unsigned EltNo)
Given a vector and an element number, see if the scalar value is already around as a register,...
LLVM_ABI MDNode * uniteAccessGroups(MDNode *AccGroups1, MDNode *AccGroups2)
Compute the union of two access-group lists.
unsigned M0(unsigned Val)
LLVM_ABI std::optional< unsigned > getVectorIntrinsicMaskArgIdx(Intrinsic::ID ID)
Returns the argument index of the mask for the vector intrinsic ID, or std::nullopt if the intrinsic ...
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool shouldSplitVectorSinCos(const TargetLibraryInfo &TLI, Type *ScalarTy, ElementCount EC, Module *M)
Returns true if the vector llvm.sincos with ScalarTy elements and EC element count has no vector libr...
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
LLVM_ABI void getShuffleMaskWithWidestElts(ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Repetitively apply widenShuffleMaskElts() for as long as it succeeds, to get the shuffle mask with wi...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
LLVM_ABI void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
LLVM_ABI bool maskContainsAllOneOrUndef(Value *Mask)
Given a mask vector of i1, Return true if any of the elements of this predicate mask are known to be ...
LLVM_ABI bool isTriviallyVectorizable(Intrinsic::ID ID)
Identify if the intrinsic is trivially vectorizable.
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
LLVM_ABI bool isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID, int OpdIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic is overloaded on the type of the operand at index OpdI...
LLVM_ABI MapVector< Instruction *, uint64_t > computeMinimumValueSizes(ArrayRef< BasicBlock * > Blocks, DemandedBits &DB, const TargetTransformInfo *TTI=nullptr)
Compute a map of integer instructions to their minimum legal type size.
LLVM_ABI bool scaleShuffleMaskElts(unsigned NumDstElts, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Attempt to narrow/widen the Mask shuffle mask to the NumDstElts target width.
LLVM_ABI int getSplatIndex(ArrayRef< int > Mask)
If all non-negative Mask elements are the same value, return that value.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.