LLVM 24.0.0git
SLPUtils.cpp
Go to the documentation of this file.
1//===- SLPUtils.cpp - SLP Vectorizer free utility helpers -----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "SLPUtils.h"
10
11#include "llvm/ADT/APInt.h"
12#include "llvm/ADT/STLExtras.h"
13#include "llvm/ADT/Sequence.h"
18#include "llvm/IR/Constants.h"
19#include "llvm/IR/DataLayout.h"
21#include "llvm/IR/IRBuilder.h"
28
29#include <algorithm>
30#include <numeric>
31#include <string>
32#include <type_traits>
33
34using namespace llvm;
35using namespace llvm::PatternMatch;
36
37namespace llvm::slpvectorizer {
38
42
43bool isBinOpIdentityConstant(const Value *V, unsigned Opcode) {
44 const auto *CI = dyn_cast<ConstantInt>(V);
45 return CI && ConstantExpr::getBinOpIdentity(Opcode, CI->getType()) == CI;
46}
47
48unsigned getReassocCombineOpcode(unsigned Opcode) {
49 switch (Opcode) {
50 case Instruction::Sub:
51 return Instruction::Add;
52 case Instruction::FSub:
53 return Instruction::FAdd;
54 default:
55 return Opcode;
56 }
57}
58
60 if (I->getOpcode() == Instruction::Sub)
61 return true;
62 if (I->getOpcode() == Instruction::FSub)
63 return I->hasAllowReassoc();
64 return I->isAssociative();
65}
66
68 auto *I = dyn_cast<Instruction>(V);
69 // Non-instructions are vector-like only if they are undef.
70 if (!I)
71 return isa<UndefValue>(V);
72 switch (I->getOpcode()) {
73 case Instruction::ExtractValue:
74 case Instruction::InsertValue:
75 return true;
76 case Instruction::ExtractElement:
77 return isa<FixedVectorType>(I->getOperand(0)->getType()) &&
78 isConstant(I->getOperand(1));
79 case Instruction::InsertElement:
80 return isa<FixedVectorType>(I->getOperand(0)->getType()) &&
81 isConstant(I->getOperand(2));
82 default:
83 return false;
84 }
85}
86
87unsigned getNumElements(Type *Ty) {
89 "ScalableVectorType is not supported.");
90 if (isVectorizedTy(Ty))
92 return 1;
93}
94
95unsigned getPartNumElems(unsigned Size, unsigned NumParts) {
96 return std::min<unsigned>(Size, bit_ceil(divideCeil(Size, NumParts)));
97}
98
99unsigned getNumElems(unsigned Size, unsigned PartNumElems, unsigned Part) {
100 return std::min<unsigned>(PartNumElems, Size - Part * PartNumElems);
101}
102
103#if !defined(NDEBUG)
104std::string shortBundleName(ArrayRef<Value *> VL, int Idx) {
105 std::string Result;
106 raw_string_ostream OS(Result);
107 if (Idx >= 0)
108 OS << "Idx: " << Idx << ", ";
109 OS << "n=" << VL.size() << " [" << *VL.front() << ", ..]";
110 return Result;
111}
112#endif
113
115 auto *It = find_if(VL, IsaPred<Instruction>);
116 if (It == VL.end())
117 return false;
120 return true;
121
122 BasicBlock *BB = I0->getParent();
123 for (Value *V : make_filter_range(iterator_range(It, VL.end()), [](Value *V) {
124 return !isa<PoisonValue>(V);
125 })) {
126 auto *II = dyn_cast<Instruction>(V);
127 if (!II)
128 return false;
129
130 if (BB != II->getParent())
131 return false;
132 }
133 return true;
134}
135
137 // Constant expressions and globals can't be vectorized like normal integer/FP
138 // constants.
139 return all_of(VL, isConstant);
140}
141
143 Value *FirstNonUndef = nullptr;
144 for (Value *V :
145 make_filter_range(VL, [](Value *V) { return !isa<UndefValue>(V); })) {
146 if (!FirstNonUndef) {
147 FirstNonUndef = V;
148 continue;
149 }
150 if (V != FirstNonUndef)
151 return false;
152 }
153 return FirstNonUndef != nullptr;
154}
155
157 if (LHS == RHS)
158 return RHS;
159 if ((LHS == Intrinsic::fma || LHS == Intrinsic::fmuladd) &&
160 (RHS == Intrinsic::fma || RHS == Intrinsic::fmuladd))
161 return Intrinsic::fma;
163}
164
165bool isCommutative(const Instruction *I, const Value *ValWithUses,
166 bool IsCopyable) {
167 if (auto *Cmp = dyn_cast<CmpInst>(I))
168 return Cmp->isCommutative();
169 if (auto *BO = dyn_cast<BinaryOperator>(I))
170 return BO->isCommutative() ||
171 (BO->getOpcode() == Instruction::Sub && ValWithUses->hasUseList() &&
172 !ValWithUses->hasNUsesOrMore(UsesLimit) &&
173 all_of(
174 ValWithUses->uses(),
175 [&](const Use &U) {
176 // Commutative, if icmp eq/ne sub, 0
177 CmpPredicate Pred;
178 if (match(U.getUser(),
179 m_ICmp(Pred, m_Specific(U.get()), m_Zero())) &&
180 (Pred == ICmpInst::ICMP_EQ || Pred == ICmpInst::ICMP_NE))
181 return true;
182 // Commutative, if abs(sub nsw, true) or abs(sub, false).
183 ConstantInt *Flag;
184 auto *I = dyn_cast<BinaryOperator>(U.get());
185 return match(U.getUser(),
186 m_Intrinsic<Intrinsic::abs>(
187 m_Specific(U.get()), m_ConstantInt(Flag))) &&
188 ((!IsCopyable && I && !I->hasNoSignedWrap()) ||
189 Flag->isOne());
190 })) ||
191 (BO->getOpcode() == Instruction::FSub && ValWithUses->hasUseList() &&
192 !ValWithUses->hasNUsesOrMore(UsesLimit) &&
193 all_of(ValWithUses->uses(), [](const Use &U) {
194 return match(U.getUser(),
195 m_Intrinsic<Intrinsic::fabs>(m_Specific(U.get())));
196 }));
197 return I->isCommutative();
198}
199
200bool isCommutative(const Instruction *I) { return isCommutative(I, I); }
201
202bool isCommutableOperand(const Instruction *I, Value *ValWithUses, unsigned Op,
203 bool IsCopyable) {
204 assert(isCommutative(I, ValWithUses, IsCopyable) &&
205 "The instruction is not commutative.");
206 if (isa<CmpInst>(I))
207 return true;
208 if (auto *BO = dyn_cast<BinaryOperator>(I)) {
209 switch (BO->getOpcode()) {
210 case Instruction::Sub:
211 case Instruction::FSub:
212 return true;
213 default:
214 break;
215 }
216 }
217 return I->isCommutableOperand(Op);
218}
219
222 // IntrinsicInst::isCommutative returns true if swapping the first "two"
223 // arguments to the intrinsic produces the same result.
224 constexpr unsigned IntrinsicNumOperands = 2;
225 return IntrinsicNumOperands;
226 }
227 return I->getNumOperands();
228}
229
230std::optional<unsigned> getElementIndex(const Value *Inst, unsigned Offset) {
231 if (auto Index = getInsertExtractIndex<InsertElementInst>(Inst, Offset))
232 return Index;
234 return Index;
235
236 unsigned Index = Offset;
237
238 const auto *IV = dyn_cast<InsertValueInst>(Inst);
239 if (!IV)
240 return std::nullopt;
241
242 Type *CurrentType = IV->getType();
243 for (unsigned I : IV->indices()) {
244 if (const auto *ST = dyn_cast<StructType>(CurrentType)) {
245 Index *= ST->getNumElements();
246 CurrentType = ST->getElementType(I);
247 } else if (const auto *AT = dyn_cast<ArrayType>(CurrentType)) {
248 Index *= AT->getNumElements();
249 CurrentType = AT->getElementType();
250 } else {
251 return std::nullopt;
252 }
253 Index += I;
254 }
255 return Index;
256}
257
259 auto *It = find_if(VL, IsaPred<Instruction>);
260 if (It == VL.end())
261 return true;
262 Instruction *MainOp = cast<Instruction>(*It);
263 unsigned Opcode = MainOp->getOpcode();
264 bool IsCmpOp = isa<CmpInst>(MainOp);
265 CmpInst::Predicate BasePred = IsCmpOp ? cast<CmpInst>(MainOp)->getPredicate()
267 return all_of(make_range(It, VL.end()), [&](Value *V) {
268 if (auto *CI = dyn_cast<CmpInst>(V))
269 return BasePred == CI->getPredicate();
270 if (auto *I = dyn_cast<Instruction>(V))
271 return I->getOpcode() == Opcode;
272 return isa<PoisonValue>(V);
273 });
274}
275
276std::optional<unsigned> getExtractIndex(const Instruction *E) {
277 unsigned Opcode = E->getOpcode();
278 assert((Opcode == Instruction::ExtractElement ||
279 Opcode == Instruction::ExtractValue) &&
280 "Expected extractelement or extractvalue instruction.");
281 if (Opcode == Instruction::ExtractElement) {
282 auto *CI = dyn_cast<ConstantInt>(E->getOperand(1));
283 if (!CI)
284 return std::nullopt;
285 // Check if the index is out of bound. We can get the source vector from
286 // operand 0.
287 unsigned Idx = CI->getZExtValue();
288 auto *EE = cast<ExtractElementInst>(E);
289 const unsigned VF = getNumElements(EE->getVectorOperandType());
290 if (Idx >= VF)
291 return std::nullopt;
292 return Idx;
293 }
294 auto *EI = cast<ExtractValueInst>(E);
295 if (EI->getNumIndices() != 1)
296 return std::nullopt;
297 return *EI->idx_begin();
298}
299
301 SmallVectorImpl<int> &Mask) {
302 Mask.clear();
303 const unsigned E = Indices.size();
304 Mask.resize(E, PoisonMaskElem);
305 for (unsigned I = 0; I < E; ++I)
306 Mask[Indices[I]] = I;
307}
308
310 assert(!Mask.empty() && "Expected non-empty mask.");
311 SmallVector<Value *> Prev(Scalars.size(),
312 PoisonValue::get(Scalars.front()->getType()));
313 Prev.swap(Scalars);
314 for (unsigned I = 0, E = Prev.size(); I < E; ++I)
315 if (Mask[I] != PoisonMaskElem)
316 Scalars[Mask[I]] = Prev[I];
317}
318
320 assert(!Mask.empty() && Reuses.size() == Mask.size() &&
321 "Expected non-empty mask.");
322 SmallVector<int> Prev(Reuses.begin(), Reuses.end());
323 Prev.swap(Reuses);
324 for (unsigned I = 0, E = Prev.size(); I < E; ++I)
325 if (Mask[I] != PoisonMaskElem)
326 Reuses[Mask[I]] = Prev[I];
327}
328
330 bool BottomOrder) {
331 assert(!Mask.empty() && "Expected non-empty mask.");
332 unsigned Sz = Mask.size();
333 if (BottomOrder) {
334 SmallVector<unsigned> PrevOrder;
335 if (Order.empty()) {
336 PrevOrder.resize(Sz);
337 std::iota(PrevOrder.begin(), PrevOrder.end(), 0);
338 } else {
339 PrevOrder.swap(Order);
340 }
341 Order.assign(Sz, Sz);
342 for (unsigned I = 0; I < Sz; ++I)
343 if (Mask[I] != PoisonMaskElem)
344 Order[I] = PrevOrder[Mask[I]];
345 if (all_of(enumerate(Order), [&](const auto &Data) {
346 return Data.value() == Sz || Data.index() == Data.value();
347 })) {
348 Order.clear();
349 return;
350 }
352 return;
353 }
354 SmallVector<int> MaskOrder;
355 if (Order.empty()) {
356 MaskOrder.resize(Sz);
357 std::iota(MaskOrder.begin(), MaskOrder.end(), 0);
358 } else {
359 inversePermutation(Order, MaskOrder);
360 }
361 reorderReuses(MaskOrder, Mask);
362 if (ShuffleVectorInst::isIdentityMask(MaskOrder, Sz)) {
363 Order.clear();
364 return;
365 }
366 Order.assign(Sz, Sz);
367 for (unsigned I = 0; I < Sz; ++I)
368 if (MaskOrder[I] != PoisonMaskElem)
369 Order[MaskOrder[I]] = I;
371}
372
374 assert(!Order.empty() &&
375 "Order is empty. Please check it before using isReverseOrder.");
376 unsigned Sz = Order.size();
377 return all_of(enumerate(Order), [&](const auto &Pair) {
378 return Pair.value() == Sz || Sz - Pair.index() - 1 == Pair.value();
379 });
380}
381
383 ArrayRef<int> FirstCluster = Mask.slice(0, Sz);
384 if (ShuffleVectorInst::isIdentityMask(FirstCluster, Sz))
385 return false;
386 for (unsigned I = Sz, E = Mask.size(); I < E; I += Sz) {
387 ArrayRef<int> Cluster = Mask.slice(I, Sz);
388 if (Cluster != FirstCluster)
389 return false;
390 }
391 return true;
392}
393
395 ArrayRef<unsigned> SecondaryOrder) {
396 assert((SecondaryOrder.empty() || Order.size() == SecondaryOrder.size()) &&
397 "Expected same size of orders");
398 size_t Sz = Order.size();
399 SmallBitVector UsedIndices(Sz);
400 for (unsigned Idx : seq<unsigned>(0, Sz)) {
401 if (Order[Idx] != Sz)
402 UsedIndices.set(Order[Idx]);
403 }
404 if (SecondaryOrder.empty()) {
405 for (unsigned Idx : seq<unsigned>(0, Sz))
406 if (Order[Idx] == Sz && !UsedIndices.test(Idx))
407 Order[Idx] = Idx;
408 } else {
409 for (unsigned Idx : seq<unsigned>(0, Sz))
410 if (SecondaryOrder[Idx] != Sz && Order[Idx] == Sz &&
411 !UsedIndices.test(SecondaryOrder[Idx]))
412 Order[Idx] = SecondaryOrder[Idx];
413 }
414}
415
417 assert(!VL.empty() && "Expected non-empty list of values.");
418 Type *Ty = VL.consume_front()->getType();
419 return all_of(VL, [&](Value *V) { return V->getType() == Ty; });
420}
421
422template <typename T>
423std::optional<unsigned> getInsertExtractIndex(const Value *Inst,
424 unsigned Offset) {
425 static_assert(std::is_same_v<T, InsertElementInst> ||
426 std::is_same_v<T, ExtractElementInst>,
427 "unsupported T");
428 const auto *IE = dyn_cast<T>(Inst);
429 if (!IE)
430 return std::nullopt;
431 // InsertElement: result is the vector, index is op 2.
432 // ExtractElement: result is scalar, vector is op 0, index is op 1.
433 constexpr bool IsInsert = std::is_same_v<T, InsertElementInst>;
434 Type *VecTy = IsInsert ? IE->getType() : IE->getOperand(0)->getType();
435 const auto *VT = dyn_cast<FixedVectorType>(VecTy);
436 if (!VT)
437 return std::nullopt;
438 const auto *CI = dyn_cast<ConstantInt>(IE->getOperand(IsInsert ? 2 : 1));
439 if (!CI)
440 return std::nullopt;
441 if (CI->getValue().uge(VT->getNumElements()))
442 return std::nullopt;
443 unsigned Index = Offset;
444 Index *= VT->getNumElements();
445 Index += CI->getZExtValue();
446 return Index;
447}
448
449// Only these two specializations are used; instantiate them here so the
450// definition can stay out of the header.
451template std::optional<unsigned>
453template std::optional<unsigned>
455
457 auto *I = dyn_cast<Instruction>(V);
458 if (!I)
459 return true;
460 return !mayHaveNonDefUseDependency(*I) &&
462 [I](Instruction *IO) {
463 return isa<PHINode>(IO) || IO->getParent() != I->getParent();
464 });
465}
466
468 auto *I = dyn_cast<Instruction>(V);
469 if (!I)
470 return true;
471 // Limits the number of uses to save compile time.
472 return !I->mayReadOrWriteMemory() && !I->hasNUsesOrMore(UsesLimit) &&
473 all_of(I->users(), [I](User *U) {
474 auto *IU = dyn_cast<Instruction>(U);
475 if (!IU)
476 return true;
477 return IU->getParent() != I->getParent() || isa<PHINode>(IU);
478 });
479}
480
484
489
490void transformScalarShuffleIndiciesToVector(unsigned VecTyNumElements,
491 SmallVectorImpl<int> &Mask) {
492 // The ShuffleBuilder implementation use shufflevector to splat an "element".
493 // But the element have different meaning for SLP (scalar) and REVEC
494 // (vector). We need to expand Mask into masks which shufflevector can use
495 // directly.
496 SmallVector<int> NewMask(Mask.size() * VecTyNumElements);
497 for (unsigned I : seq<unsigned>(Mask.size()))
498 for (auto [J, MaskV] : enumerate(MutableArrayRef(NewMask).slice(
499 I * VecTyNumElements, VecTyNumElements)))
500 MaskV = Mask[I] == PoisonMaskElem ? PoisonMaskElem
501 : Mask[I] * VecTyNumElements + J;
502 Mask.swap(NewMask);
503}
504
506 if (VL.empty())
507 return 0;
509 return 0;
510 auto *SV = cast<ShuffleVectorInst>(VL.front());
511 unsigned SVNumElements =
512 cast<FixedVectorType>(SV->getOperand(0)->getType())->getNumElements();
513 unsigned ShuffleMaskSize = SV->getShuffleMask().size();
514 if (SVNumElements % ShuffleMaskSize != 0)
515 return 0;
516 unsigned GroupSize = SVNumElements / ShuffleMaskSize;
517 if (GroupSize == 0 || (VL.size() % GroupSize) != 0)
518 return 0;
519 unsigned NumGroup = 0;
520 for (size_t I = 0, E = VL.size(); I != E; I += GroupSize) {
521 auto *SV = cast<ShuffleVectorInst>(VL[I]);
522 Value *Src = SV->getOperand(0);
523 ArrayRef<Value *> Group = VL.slice(I, GroupSize);
524 SmallBitVector ExpectedIndex(GroupSize);
525 if (!all_of(Group, [&](Value *V) {
526 auto *SV = cast<ShuffleVectorInst>(V);
527 // From the same source.
528 if (SV->getOperand(0) != Src)
529 return false;
530 int Index;
531 if (!SV->isExtractSubvectorMask(Index))
532 return false;
533 ExpectedIndex.set(Index / ShuffleMaskSize);
534 return true;
535 }))
536 return 0;
537 if (!ExpectedIndex.all())
538 return 0;
539 ++NumGroup;
540 }
541 assert(NumGroup == (VL.size() / GroupSize) && "Unexpected number of groups");
542 return NumGroup;
543}
544
546 assert(getShufflevectorNumGroups(VL) && "Not supported shufflevector usage.");
547 auto *SV = cast<ShuffleVectorInst>(VL.front());
548 unsigned SVNumElements =
549 cast<FixedVectorType>(SV->getOperand(0)->getType())->getNumElements();
550 SmallVector<int> Mask;
551 unsigned AccumulateLength = 0;
552 for (Value *V : VL) {
553 auto *SV = cast<ShuffleVectorInst>(V);
554 for (int M : SV->getShuffleMask())
555 Mask.push_back(M == PoisonMaskElem ? PoisonMaskElem
556 : AccumulateLength + M);
557 AccumulateLength += SVNumElements;
558 }
559 return Mask;
560}
561
562/// Checks if the vector of instructions can be represented as a shuffle, like:
563/// %x0 = extractelement <4 x i8> %x, i32 0
564/// %x3 = extractelement <4 x i8> %x, i32 3
565/// %y1 = extractelement <4 x i8> %y, i32 1
566/// %y2 = extractelement <4 x i8> %y, i32 2
567/// %x0x0 = mul i8 %x0, %x0
568/// %x3x3 = mul i8 %x3, %x3
569/// %y1y1 = mul i8 %y1, %y1
570/// %y2y2 = mul i8 %y2, %y2
571/// %ins1 = insertelement <4 x i8> poison, i8 %x0x0, i32 0
572/// %ins2 = insertelement <4 x i8> %ins1, i8 %x3x3, i32 1
573/// %ins3 = insertelement <4 x i8> %ins2, i8 %y1y1, i32 2
574/// %ins4 = insertelement <4 x i8> %ins3, i8 %y2y2, i32 3
575/// ret <4 x i8> %ins4
576/// can be transformed into:
577/// %1 = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 3, i32 5,
578/// i32 6>
579/// %2 = mul <4 x i8> %1, %1
580/// ret <4 x i8> %2
581/// Mask will return the Shuffle Mask equivalent to the extracted elements.
582/// TODO: Can we split off and reuse the shuffle mask detection from
583/// ShuffleVectorInst/getShuffleCost?
584std::optional<TargetTransformInfo::ShuffleKind>
586 AssumptionCache *AC) {
587 const auto *It = find_if(VL, IsaPred<ExtractElementInst>);
588 if (It == VL.end())
589 return std::nullopt;
590 unsigned Size = accumulate(VL, 0u, [](unsigned S, Value *V) {
591 auto *EI = dyn_cast<ExtractElementInst>(V);
592 if (!EI)
593 return S;
594 auto *VTy = dyn_cast<FixedVectorType>(EI->getVectorOperandType());
595 if (!VTy)
596 return S;
597 return std::max(S, VTy->getNumElements());
598 });
599
600 Value *Vec1 = nullptr;
601 Value *Vec2 = nullptr;
602 bool HasNonUndefVec = any_of(make_isa_range<ExtractElementInst>(VL),
603 [&](ExtractElementInst *EE) {
604 Value *Vec = EE->getVectorOperand();
605 if (isa<UndefValue>(Vec))
606 return false;
607 return isGuaranteedNotToBePoison(Vec, AC);
608 });
609 enum ShuffleMode { Unknown, Select, Permute };
610 ShuffleMode CommonShuffleMode = Unknown;
611 Mask.assign(VL.size(), PoisonMaskElem);
612 for (unsigned I = 0, E = VL.size(); I < E; ++I) {
613 // Undef, or a copyable lane modeled on an extract main op, can be
614 // represented as an undef element in a vector.
615 if (isa<UndefValue>(VL[I]))
616 continue;
617 auto *EI = dyn_cast<ExtractElementInst>(VL[I]);
618 if (!EI)
619 continue;
620 if (isa<ScalableVectorType>(EI->getVectorOperandType()))
621 return std::nullopt;
622 auto *Vec = EI->getVectorOperand();
623 // We can extractelement from undef or poison vector.
625 continue;
626 // All vector operands must have the same number of vector elements.
627 if (isa<UndefValue>(Vec)) {
628 Mask[I] = I;
629 } else {
630 if (isa<UndefValue>(EI->getIndexOperand()))
631 continue;
632 auto *Idx = dyn_cast<ConstantInt>(EI->getIndexOperand());
633 if (!Idx)
634 return std::nullopt;
635 // Undefined behavior if Idx is negative or >= Size.
636 if (Idx->getValue().uge(Size))
637 continue;
638 unsigned IntIdx = Idx->getValue().getZExtValue();
639 Mask[I] = IntIdx;
640 }
641 if (isUndefVector(Vec).all() && HasNonUndefVec)
642 continue;
643 // For correct shuffling we have to have at most 2 different vector operands
644 // in all extractelement instructions.
645 if (!Vec1 || Vec1 == Vec) {
646 Vec1 = Vec;
647 } else if (!Vec2 || Vec2 == Vec) {
648 Vec2 = Vec;
649 Mask[I] += Size;
650 } else {
651 return std::nullopt;
652 }
653 if (CommonShuffleMode == Permute)
654 continue;
655 // If the extract index is not the same as the operation number, it is a
656 // permutation.
657 if (Mask[I] % Size != I) {
658 CommonShuffleMode = Permute;
659 continue;
660 }
661 CommonShuffleMode = Select;
662 }
663 // If we're not crossing lanes in different vectors, consider it as blending.
664 if (CommonShuffleMode == Select && Vec2)
666 // If Vec2 was never used, we have a permutation of a single vector, otherwise
667 // we have permutation of 2 vectors.
670}
671
673 IRBuilderBase &Builder, Value *Vec, Value *V, unsigned Index,
674 function_ref<Value *(Value *, Value *, ArrayRef<int>)> Generator) {
675 if (isa<PoisonValue>(Vec) && isa<PoisonValue>(V))
676 return Vec;
677 const unsigned SubVecVF = getNumElements(V->getType());
678 // Create shuffle, insertvector requires that index is multiple of
679 // the subvector length.
680 const unsigned VecVF = getNumElements(Vec->getType());
681 SmallVector<int> Mask(VecVF, PoisonMaskElem);
682 if (isa<PoisonValue>(Vec)) {
683 auto *Begin = std::next(Mask.begin(), Index);
684 std::iota(Begin, std::next(Begin, SubVecVF), 0);
685 Vec = Builder.CreateShuffleVector(V, Mask);
686 return Vec;
687 }
688 std::iota(Mask.begin(), Mask.end(), 0);
689 std::iota(std::next(Mask.begin(), Index),
690 std::next(Mask.begin(), Index + SubVecVF), VecVF);
691 if (Generator)
692 return Generator(Vec, V, Mask);
693 // 1. Resize V to the size of Vec.
694 SmallVector<int> ResizeMask(VecVF, PoisonMaskElem);
695 std::iota(ResizeMask.begin(), std::next(ResizeMask.begin(), SubVecVF), 0);
696 V = Builder.CreateShuffleVector(V, ResizeMask);
697 // 2. Insert V into Vec.
698 return Builder.CreateShuffleVector(Vec, V, Mask);
699}
700
702 unsigned SubVecVF, unsigned Index) {
703 SmallVector<int> Mask(SubVecVF, PoisonMaskElem);
704 std::iota(Mask.begin(), Mask.end(), Index);
705 return Builder.CreateShuffleVector(Vec, Mask);
706}
707
709 SmallBitVector UseMask(VF, true);
710 for (auto [Idx, Value] : enumerate(Mask)) {
711 if (Value == PoisonMaskElem) {
712 if (MaskArg == UseMask::UndefsAsMask)
713 UseMask.reset(Idx);
714 continue;
715 }
716 if (MaskArg == UseMask::FirstArg && Value < VF)
717 UseMask.reset(Value);
718 else if (MaskArg == UseMask::SecondArg && Value >= VF)
719 UseMask.reset(Value - VF);
720 }
721 return UseMask;
722}
723
724template <bool IsPoisonOnly>
726 SmallBitVector Res(UseMask.empty() ? 1 : UseMask.size(), true);
727 using T = std::conditional_t<IsPoisonOnly, PoisonValue, UndefValue>;
728 if (isa<T>(V))
729 return Res;
730 auto *VecTy = dyn_cast<FixedVectorType>(V->getType());
731 if (!VecTy)
732 return Res.reset();
733 auto *C = dyn_cast<Constant>(V);
734 if (!C) {
735 if (!UseMask.empty()) {
736 const Value *Base = V;
737 while (auto *II = dyn_cast<InsertElementInst>(Base)) {
738 Base = II->getOperand(0);
739 if (isa<T>(II->getOperand(1)))
740 continue;
741 std::optional<unsigned> Idx = getElementIndex(II);
742 if (!Idx) {
743 Res.reset();
744 return Res;
745 }
746 if (*Idx < UseMask.size() && !UseMask.test(*Idx))
747 Res.reset(*Idx);
748 }
749 // TODO: Add analysis for shuffles here too.
750 if (V == Base) {
751 Res.reset();
752 } else {
753 SmallBitVector SubMask(UseMask.size(), false);
754 Res &= isUndefVector<IsPoisonOnly>(Base, SubMask);
755 }
756 } else {
757 Res.reset();
758 }
759 return Res;
760 }
761 for (unsigned I = 0, E = VecTy->getNumElements(); I != E; ++I) {
762 if (Constant *Elem = C->getAggregateElement(I))
763 if (!isa<T>(Elem) &&
764 (UseMask.empty() || (I < UseMask.size() && !UseMask.test(I))))
765 Res.reset(I);
766 }
767 return Res;
768}
769
771 const SmallBitVector &);
773 const SmallBitVector &);
774
777 const TargetTransformInfo *TTI) {
778 if (!UserInst)
779 return false;
780 unsigned Opcode = UserInst->getOpcode();
781 switch (Opcode) {
782 case Instruction::Load: {
783 LoadInst *LI = cast<LoadInst>(UserInst);
784 return (LI->getPointerOperand() == Scalar);
785 }
786 case Instruction::Store: {
787 StoreInst *SI = cast<StoreInst>(UserInst);
788 return (SI->getPointerOperand() == Scalar);
789 }
790 case Instruction::Call: {
791 CallInst *CI = cast<CallInst>(UserInst);
793 return any_of(enumerate(CI->args()), [&](auto &&Arg) {
794 return isVectorIntrinsicWithScalarOpAtArg(ID, Arg.index(), TTI) &&
795 Arg.value().get() == Scalar;
796 });
797 }
798 default:
799 return false;
800 }
801}
802
810
812 if (LoadInst *LI = dyn_cast<LoadInst>(I))
813 return LI->isSimple();
815 return SI->isSimple();
817 return !MI->isVolatile();
818 return true;
819}
820
821bool isSelectedBaseLoad(Type *ScalarTy, ArrayRef<Value *> PointerOps,
822 const DataLayout &DL, Value *&TrueBase,
823 Value *&FalseBase,
824 SmallVectorImpl<Value *> &Conditions) {
825 TrueBase = nullptr;
826 FalseBase = nullptr;
827 uint64_t ScalarSize = DL.getTypeStoreSize(ScalarTy);
828 Conditions.assign(PointerOps.size(), nullptr);
829 for (auto [Idx, P] : enumerate(PointerOps)) {
830 Value *Base = P;
831 uint64_t Offset = 0;
832 if (auto *GEP = dyn_cast<GetElementPtrInst>(P)) {
833 APInt OffsetAP(DL.getIndexTypeSizeInBits(GEP->getType()), 0);
834 if (!GEP->accumulateConstantOffset(DL, OffsetAP) || OffsetAP.isNegative())
835 return false;
836 Offset = OffsetAP.getZExtValue();
837 Base = GEP->getPointerOperand();
838 }
839 auto *Sel = dyn_cast<SelectInst>(Base);
840 if (!Sel)
841 return false;
842 Value *T = Sel->getTrueValue();
843 Value *F = Sel->getFalseValue();
844 if (!TrueBase) {
845 if (T == F)
846 return false;
847 TrueBase = T;
848 FalseBase = F;
849 } else if (TrueBase != T || FalseBase != F) {
850 return false;
851 }
852 // Lane Idx must be at exactly Base + Idx * sizeof(ScalarTy); codegen reads
853 // contiguously from TrueBase/FalseBase starting at lane 0.
854 if (Offset != static_cast<uint64_t>(Idx) * ScalarSize)
855 return false;
856 Conditions[Idx] = Sel->getCondition();
857 }
858 return TrueBase != nullptr;
859}
860
862 function_ref<bool(Value *)> IsGEPLane,
863 const DataLayout &DL) {
864 constexpr unsigned IndexIdx = 1;
865 Type *VL0Ty = VL0->getOperand(IndexIdx)->getType();
866 Type *PtrIdxTy =
867 DL.getIndexType(VL0->getOperand(0)->getType()->getScalarType());
868 bool AllSameTy = true;
869 bool HasNonConstIdx = false;
870 bool ConstsFitVL0Ty = true;
871 for (Value *V : make_filter_range(VL, IsGEPLane)) {
872 Value *Op = cast<GetElementPtrInst>(V)->getOperand(IndexIdx);
873 if (Op->getType() != VL0Ty)
874 AllSameTy = false;
875 auto *CI = dyn_cast<ConstantInt>(Op);
876 if (!CI) {
877 // Non-constant indices are not cast, they must have the main op type.
878 if (Op->getType() != VL0Ty)
879 return nullptr;
880 HasNonConstIdx = true;
881 continue;
882 }
883 if (!CI->getValue().isSignedIntN(VL0Ty->getIntegerBitWidth()))
884 ConstsFitVL0Ty = false;
885 }
886 if (AllSameTy)
887 return VL0Ty;
888 if (!HasNonConstIdx || VL0Ty == PtrIdxTy)
889 return PtrIdxTy;
890 return ConstsFitVL0Ty ? VL0Ty : nullptr;
891}
892
894 SmallPtrSet<Value *, 16> UniquePtrs(llvm::from_range, PointerOps);
895 if (UniquePtrs.size() != PointerOps.size())
896 return false;
897 auto IsConstantOffsetPtr = [](Value *P) {
899 return !GEP ||
900 (GEP->getNumOperands() == 2 && isConstant(GEP->getOperand(1)));
901 };
902 auto *RefIt = find_if_not(PointerOps, IsConstantOffsetPtr);
903 if (RefIt == PointerOps.end())
904 return false;
905 auto *RefGEP = dyn_cast<GetElementPtrInst>(*RefIt);
906 if (!RefGEP || RefGEP->getNumOperands() != 2)
907 return false;
908 Value *Base = RefGEP->getPointerOperand();
909 Type *PtrTy = RefGEP->getType();
910 Type *SrcElemTy = RefGEP->getSourceElementType();
911 // The stride and the (optional) cast opcode of the runtime indices.
912 Value *Stride = nullptr;
913 unsigned CastOpcode = 0;
914 for (Value *P : PointerOps) {
915 if (P->getType() != PtrTy)
916 return false;
917 if (P == Base)
918 continue;
920 if (!GEP || GEP->getNumOperands() != 2 ||
921 GEP->getPointerOperand() != Base ||
922 GEP->getSourceElementType() != SrcElemTy)
923 return false;
924 Value *Idx = GEP->getOperand(1);
925 if (isConstant(Idx))
926 continue;
927 unsigned LaneCastOpcode = 0;
928 if (auto *Cast = dyn_cast<CastInst>(Idx)) {
929 LaneCastOpcode = Cast->getOpcode();
930 Idx = Cast->getOperand(0);
931 }
932 Value *LaneStride = Idx;
933 if (auto *BO = dyn_cast<BinaryOperator>(Idx)) {
934 if (isa<Constant>(BO->getOperand(1)))
935 LaneStride = BO->getOperand(0);
936 else if (isa<Constant>(BO->getOperand(0)))
937 LaneStride = BO->getOperand(1);
938 }
939 if (!Stride) {
940 Stride = LaneStride;
941 CastOpcode = LaneCastOpcode;
942 continue;
943 }
944 if (LaneStride != Stride || LaneCastOpcode != CastOpcode)
945 return false;
946 }
947 return Stride != nullptr;
948}
949
951 bool ExtendingManyInputs) {
952 if (SubMask.empty())
953 return;
954 assert(
955 (!ExtendingManyInputs || SubMask.size() > Mask.size() ||
956 // Check if input scalars were extended to match the size of other node.
957 (SubMask.size() == Mask.size() && Mask.back() == PoisonMaskElem)) &&
958 "SubMask with many inputs support must be larger than the mask.");
959 if (Mask.empty()) {
960 Mask.append(SubMask.begin(), SubMask.end());
961 return;
962 }
963 SmallVector<int> NewMask(SubMask.size(), PoisonMaskElem);
964 int TermValue = std::min(Mask.size(), SubMask.size());
965 for (int I = 0, E = SubMask.size(); I < E; ++I) {
966 if (SubMask[I] == PoisonMaskElem ||
967 (!ExtendingManyInputs &&
968 (SubMask[I] >= TermValue || Mask[SubMask[I]] >= TermValue)))
969 continue;
970 NewMask[I] = Mask[SubMask[I]];
971 }
972 Mask.swap(NewMask);
973}
974
976 const size_t Sz = Order.size();
977 SmallBitVector UnusedIndices(Sz, /*t=*/true);
978 SmallBitVector MaskedIndices(Sz);
979 for (unsigned I = 0; I < Sz; ++I) {
980 if (Order[I] < Sz)
981 UnusedIndices.reset(Order[I]);
982 else
983 MaskedIndices.set(I);
984 }
985 if (MaskedIndices.none())
986 return;
987 assert(UnusedIndices.count() == MaskedIndices.count() &&
988 "Non-synced masked/available indices.");
989 int Idx = UnusedIndices.find_first();
990 int MIdx = MaskedIndices.find_first();
991 while (MIdx >= 0) {
992 assert(Idx >= 0 && "Indices must be synced.");
993 Order[MIdx] = Idx;
994 Idx = UnusedIndices.find_next(Idx);
995 MIdx = MaskedIndices.find_next(MIdx);
996 }
997}
998
1000 unsigned Opcode0, unsigned Opcode1) {
1001 unsigned ScalarTyNumElements = getNumElements(ScalarTy);
1002 SmallBitVector OpcodeMask(VL.size() * ScalarTyNumElements, false);
1003 for (unsigned Lane : seq<unsigned>(VL.size())) {
1004 if (isa<PoisonValue>(VL[Lane]))
1005 continue;
1006 if (cast<Instruction>(VL[Lane])->getOpcode() == Opcode1)
1007 OpcodeMask.set(Lane * ScalarTyNumElements,
1008 Lane * ScalarTyNumElements + ScalarTyNumElements);
1009 }
1010 return OpcodeMask;
1011}
1012
1014 assert(none_of(Val, [](Constant *C) { return C->getType()->isVectorTy(); }) &&
1015 "Expected scalar constants.");
1016 SmallVector<Constant *> NewVal(Val.size() * VF);
1017 for (auto [I, V] : enumerate(Val))
1018 std::fill_n(NewVal.begin() + I * VF, VF, V);
1019 return NewVal;
1020}
1021
1023 switch (Opcode) {
1024 case Instruction::UDiv:
1025 return Intrinsic::masked_udiv;
1026 case Instruction::SDiv:
1027 return Intrinsic::masked_sdiv;
1028 case Instruction::URem:
1029 return Intrinsic::masked_urem;
1030 case Instruction::SRem:
1031 return Intrinsic::masked_srem;
1032 default:
1033 llvm_unreachable("Unexpected opcode");
1034 }
1035}
1036
1037/// Returns true if \p I is a part of a single-use chain, computing an address,
1038/// which does not pay off the vectorization: a constant table is accessed by a
1039/// gather, while the indices, unrelated between the lanes, require a full
1040/// buildvector, unlike the ones, shifted by a constant from a common base.
1042 constexpr unsigned MaxIndexChainLength = 3;
1043 // A constant shift of a common base is a cheap buildvector, while the loads
1044 // are vectorized together with the indices, computed from them.
1045 auto IsProfitableOperand = [](const Value *V) {
1046 if (isa<Constant>(V))
1047 return true;
1048 if (const auto *Cast = dyn_cast<CastInst>(V); Cast && Cast->hasOneUse())
1049 V = Cast->getOperand(0);
1050 return isa<LoadInst>(V);
1051 };
1052 const User *U = I->user_back();
1053 for ([[maybe_unused]] unsigned _ : seq<unsigned>(MaxIndexChainLength)) {
1054 if (const auto *GEP = dyn_cast<GetElementPtrInst>(U))
1055 return isa<Constant>(GEP->getPointerOperand()) ||
1056 none_of(I->operand_values(), IsProfitableOperand);
1057 if (!isa<Instruction>(U) || !U->hasOneUse())
1058 return false;
1059 U = U->user_back();
1060 }
1061 return false;
1062}
1063
1065 if (!I->hasOneUse() || isNonProfitableIndex(I))
1066 return false;
1067 // The operation with the identity or the absorbing constant is folded away
1068 // before the codegen, the vector node only repacks the lanes.
1069 if (const auto *BO = dyn_cast<BinaryOperator>(I)) {
1070 unsigned Opcode = BO->getOpcode();
1071 Type *Ty = BO->getType();
1072 for (unsigned Idx : seq<unsigned>(2)) {
1073 const auto *C = dyn_cast<Constant>(BO->getOperand(Idx));
1075 Opcode, Ty, /*AllowRHSConstant=*/Idx == 1) ||
1077 Opcode, Ty, /*AllowLHSConstant=*/Idx == 0)))
1078 return false;
1079 }
1080 }
1081 const User *U = I->user_back();
1084 if (isa<CastInst>(I))
1085 return !isa<FPToSIInst, FPToUIInst>(I) &&
1086 (!isa<CastInst>(U) || U->hasOneUse());
1088 I);
1089}
1090
1091Instruction *lookThroughCastRoundTrip(Value *V, bool MustBeElidable) {
1092 auto *Wide = dyn_cast<FPExtInst>(V);
1093 if (!Wide || !Wide->hasOneUse())
1094 return nullptr;
1095 auto *Narrow = dyn_cast<FPTruncInst>(Wide->getOperand(0));
1096 if (!Narrow || !Narrow->hasOneUse())
1097 return nullptr;
1098 Value *Src = Narrow->getOperand(0);
1099 if (!isa<Instruction>(Src) || Src->getType() != Wide->getType())
1100 return nullptr;
1101 if (MustBeElidable && !(Wide->hasAllowContract() && Wide->hasNoNaNs() &&
1102 Wide->hasNoInfs() && Narrow->hasAllowContract()))
1103 return nullptr;
1104 return Narrow;
1105}
1106
1107namespace {
1108
1109/// Shifts and the mask accumulated from the narrow ops on the current path:
1110/// the shifts above and at the narrow level, the bitwidth of the narrow ops
1111/// (0 if none) and the mask from the absorbed narrow ands.
1112struct NarrowedChainState {
1113 unsigned Shift = 0;
1114 unsigned NarrowShift = 0;
1115 unsigned NarrowBW = 0;
1116 APInt NarrowMask = APInt(1, 0);
1117
1118 /// The mask for the absorbed narrow ops in the leaf type, applied before
1119 /// widening and shifting; all-ones if nothing was absorbed.
1120 APInt getMask(unsigned LeafBW) const {
1121 if (NarrowBW == 0)
1122 return APInt::getAllOnes(LeafBW);
1123 return (NarrowMask & (APInt::getAllOnes(NarrowBW) << NarrowShift))
1124 .lshr(NarrowShift)
1125 .trunc(LeafBW);
1126 }
1127};
1128
1129} // namespace
1130
1131static void
1132collectNarrowedLeavesImpl(Value *V, unsigned RdxOpcode, unsigned WideBW,
1133 NarrowedChainState S, unsigned Depth,
1134 unsigned MaxDepth,
1136 SmallVectorImpl<Instruction *> &ChainInsts) {
1137 if (Depth < MaxDepth) {
1138 if (auto *Z = dyn_cast<ZExtInst>(V);
1139 Z && Z->getSrcTy()->isIntegerTy() && !Z->getSrcTy()->isIntegerTy(1)) {
1140 ChainInsts.push_back(Z);
1141 return collectNarrowedLeavesImpl(Z->getOperand(0), RdxOpcode, WideBW, S,
1142 Depth + 1, MaxDepth, Leaves, ChainInsts);
1143 }
1144 if (auto *BO = dyn_cast<BinaryOperator>(V)) {
1145 if (BO->getOpcode() == RdxOpcode) {
1146 ChainInsts.push_back(BO);
1147 collectNarrowedLeavesImpl(BO->getOperand(0), RdxOpcode, WideBW, S,
1148 Depth + 1, MaxDepth, Leaves, ChainInsts);
1149 collectNarrowedLeavesImpl(BO->getOperand(1), RdxOpcode, WideBW, S,
1150 Depth + 1, MaxDepth, Leaves, ChainInsts);
1151 return;
1152 }
1153 const APInt *Amt;
1154 unsigned BW = V->getType()->getScalarSizeInBits();
1155 auto *Z = dyn_cast<ZExtInst>(BO->getOperand(0));
1156 if (BO->getOpcode() == Instruction::Shl && Z && S.NarrowBW == 0 &&
1157 match(BO->getOperand(1), m_APInt(Amt)) && Amt->ult(BW) &&
1158 Z->getSrcTy()->isIntegerTy() && !Z->getSrcTy()->isIntegerTy(1) &&
1159 (BW == WideBW ||
1160 Z->getSrcTy()->getIntegerBitWidth() + Amt->getZExtValue() <= BW) &&
1161 S.Shift + Amt->getZExtValue() < WideBW) {
1162 ChainInsts.push_back(BO);
1163 ChainInsts.push_back(Z);
1164 S.Shift += Amt->getZExtValue();
1165 return collectNarrowedLeavesImpl(Z->getOperand(0), RdxOpcode, WideBW, S,
1166 Depth + 1, MaxDepth, Leaves,
1167 ChainInsts);
1168 }
1169 // Narrow shls fold into the shift and narrow ands into the mask; the
1170 // mask clears the bits the shls shift out. Only same-width ops compose
1171 // on one path, and the combined shift must stay a valid shift amount in
1172 // both types.
1173 if (BW < WideBW && (S.NarrowBW == 0 || BW == S.NarrowBW)) {
1174 if (BO->getOpcode() == Instruction::Shl &&
1175 match(BO->getOperand(1), m_APInt(Amt)) && Amt->ult(BW) &&
1176 S.NarrowShift + Amt->getZExtValue() < BW &&
1177 S.Shift + S.NarrowShift + Amt->getZExtValue() < WideBW) {
1178 ChainInsts.push_back(BO);
1179 if (BO->hasNoUnsignedWrap() && S.NarrowBW == 0) {
1180 S.Shift += Amt->getZExtValue();
1181 // Lossless shls shift out only known-zero bits; record them as
1182 // the mask so matching lanes can form a splat.
1183 S.NarrowBW = BW;
1184 S.NarrowMask = APInt::getLowBitsSet(BW, BW - Amt->getZExtValue());
1185 } else {
1186 if (S.NarrowBW == 0) {
1187 S.NarrowBW = BW;
1188 S.NarrowMask = APInt::getAllOnes(BW);
1189 }
1190 S.NarrowShift += Amt->getZExtValue();
1191 }
1192 return collectNarrowedLeavesImpl(BO->getOperand(0), RdxOpcode, WideBW,
1193 S, Depth + 1, MaxDepth, Leaves,
1194 ChainInsts);
1195 }
1196 Value *X;
1197 if (match(BO, m_c_And(m_Value(X), m_APInt(Amt)))) {
1198 ChainInsts.push_back(BO);
1199 if (S.NarrowBW == 0) {
1200 S.NarrowBW = BW;
1201 S.NarrowMask = APInt::getAllOnes(BW);
1202 }
1203 S.NarrowMask &= *Amt << S.NarrowShift;
1204 return collectNarrowedLeavesImpl(X, RdxOpcode, WideBW, S, Depth + 1,
1205 MaxDepth, Leaves, ChainInsts);
1206 }
1207 }
1208 }
1209 }
1210 Leaves.emplace_back(V, S.Shift + S.NarrowShift,
1211 S.getMask(V->getType()->getScalarSizeInBits()));
1212}
1213
1214void collectNarrowedLeaves(Value *V, unsigned RdxOpcode, unsigned WideBW,
1215 unsigned MaxDepth,
1217 SmallVectorImpl<Instruction *> &ChainInsts) {
1218 collectNarrowedLeavesImpl(V, RdxOpcode, WideBW, NarrowedChainState(),
1219 /*Depth=*/0, MaxDepth, Leaves, ChainInsts);
1220}
1221
1223 assert(F && "Expected function.");
1224 return F->hasOptSize() ? TTI::TCK_CodeSize : TTI::TCK_RecipThroughput;
1225}
1226
1227/// Checks if \p V is a zero-extended sub-field of a wider integer scalar.
1228/// Returns the source scalar, the field width and the field offset.
1229static std::optional<std::tuple<Value *, unsigned, unsigned>>
1231 if (!V->getType()->isIntegerTy())
1232 return std::nullopt;
1233 // Field offset for the field-aligned shift amount, if the shifted value of
1234 // the given bit width keeps at least one full field.
1235 auto GetFieldOffset = [](const APInt *Amt, unsigned BitWidth,
1236 unsigned FieldWidth) -> std::optional<unsigned> {
1237 uint64_t ShAmt = Amt->getLimitedValue(BitWidth);
1238 if (ShAmt % FieldWidth != 0 || ShAmt + FieldWidth > BitWidth)
1239 return std::nullopt;
1240 return ShAmt / FieldWidth;
1241 };
1242 // Checks if the low bits of Val are a sub-field of the given width of a
1243 // wider integer scalar. Val is a scalar integer, since V is one, and so is
1244 // the matched source.
1245 auto MatchLowField =
1246 [&](Value *Val,
1247 unsigned FieldWidth) -> std::optional<std::pair<Value *, unsigned>> {
1248 Value *Src;
1249 const APInt *Amt;
1250 // Only the low bits of Val are observed, so lshr and ashr are equivalent.
1251 if (match(Val, m_Trunc(m_Shr(m_Value(Src), m_APInt(Amt)))) ||
1252 match(Val, m_Shr(m_Value(Src), m_APInt(Amt)))) {
1253 if (std::optional<unsigned> Offset = GetFieldOffset(
1254 Amt, Src->getType()->getIntegerBitWidth(), FieldWidth)) {
1255 // The truncation of the shifted value keeps the field, look through it.
1256 match(Src, m_Trunc(m_Value(Src)));
1257 return std::make_pair(Src, *Offset);
1258 }
1259 return std::nullopt;
1260 }
1261 if (match(Val, m_Trunc(m_Value(Src))) &&
1262 Src->getType()->getIntegerBitWidth() >= FieldWidth)
1263 return std::make_pair(Src, 0u);
1264 // Val itself is the source of its low field.
1265 if (Val->getType()->getIntegerBitWidth() > FieldWidth)
1266 return std::make_pair(Val, 0u);
1267 return std::nullopt;
1268 };
1269 Value *Val;
1270 const APInt *Mask;
1271 // and Val, (1 << FieldWidth) - 1 or zext i<FieldWidth> Val - the low bits of
1272 // Val.
1273 unsigned FieldWidth = 0;
1274 if (match(V, m_c_And(m_Value(Val), m_APInt(Mask))) && Mask->isMask())
1275 FieldWidth = Mask->popcount();
1276 else if (match(V, m_ZExt(m_Value(Val))))
1277 FieldWidth = Val->getType()->getIntegerBitWidth();
1278 if (FieldWidth != 0) {
1279 if (std::optional<std::pair<Value *, unsigned>> Field =
1280 MatchLowField(Val, FieldWidth))
1281 return std::make_tuple(Field->first, FieldWidth, Field->second);
1282 return std::nullopt;
1283 }
1284 unsigned LaneWidth = V->getType()->getIntegerBitWidth();
1285 Value *Src;
1286 const APInt *Amt;
1287 if (match(V, m_Trunc(m_LShr(m_Value(Src), m_APInt(Amt))))) {
1288 unsigned SrcWidth = Src->getType()->getIntegerBitWidth();
1289 uint64_t ShAmt = Amt->getLimitedValue(SrcWidth);
1290 // The field itself, if the lane width is the field width.
1291 if (std::optional<unsigned> Offset =
1292 GetFieldOffset(Amt, SrcWidth, LaneWidth))
1293 return std::make_tuple(Src, LaneWidth, *Offset);
1294 // The zero-extended top field of the source.
1295 unsigned FieldWidth = SrcWidth - ShAmt;
1296 if (FieldWidth > 0 && FieldWidth < LaneWidth && ShAmt % FieldWidth == 0)
1297 return std::make_tuple(Src, FieldWidth, ShAmt / FieldWidth);
1298 return std::nullopt;
1299 }
1300 if (match(V, m_LShr(m_Value(Src), m_APInt(Amt)))) {
1301 // The zero-extended top field of the source, if the result keeps exactly
1302 // one field. Look through a truncation of the shifted value.
1303 unsigned ShfWidth = Src->getType()->getIntegerBitWidth();
1304 uint64_t ShAmt = Amt->getLimitedValue(ShfWidth);
1305 unsigned FieldWidth = ShfWidth - ShAmt;
1306 if (FieldWidth > 0 && ShAmt % FieldWidth == 0) {
1307 match(Src, m_Trunc(m_Value(Src)));
1308 return std::make_tuple(Src, FieldWidth, ShAmt / FieldWidth);
1309 }
1310 return std::nullopt;
1311 }
1312 if (match(V, m_Trunc(m_Value(Src))))
1313 return std::make_tuple(Src, LaneWidth, 0u);
1314 return std::nullopt;
1315}
1316
1317std::optional<std::tuple<Value *, unsigned, SmallVector<int>>>
1319 // Splats are emitted as broadcasts, sub-fields of a constant are folded.
1320 // The bitcast to the field vector maps lane 0 to the least significant
1321 // field on little-endian targets only.
1322 if (VL.size() < 2 || !VL.front()->getType()->isIntegerTy() || isSplat(VL) ||
1323 DL.isBigEndian())
1324 return std::nullopt;
1325 Value *Src = nullptr;
1326 unsigned FieldWidth = 0;
1328 for (auto [Idx, V] : make_filter_range(enumerate(VL), [](const auto &P) {
1329 return !isa<UndefValue>(P.value());
1330 })) {
1331 if (V->getType() != VL.front()->getType())
1332 return std::nullopt;
1333 std::optional<std::tuple<Value *, unsigned, unsigned>> Field =
1335 if (!Field || (Src && (Src != std::get<0>(*Field) ||
1336 FieldWidth != std::get<1>(*Field))))
1337 return std::nullopt;
1338 Src = std::get<0>(*Field);
1339 FieldWidth = std::get<1>(*Field);
1340 Mask[Idx] = std::get<2>(*Field);
1341 }
1342 // The field width is a whole number of bytes and divides the source
1343 // exactly, same as for the packing layout, so the source bitcasts to the
1344 // field vector.
1345 if (!Src || isa<Constant>(Src) || FieldWidth % 8 != 0 ||
1346 Src->getType()->getIntegerBitWidth() % FieldWidth != 0)
1347 return std::nullopt;
1348 // The same field in every lane is a splat, emitted as a broadcast.
1349 if (all_of(Mask, [First = *find_if(Mask, not_equal_to(PoisonMaskElem))](
1350 int MaskElt) {
1351 return MaskElt == PoisonMaskElem || MaskElt == First;
1352 }))
1353 return std::nullopt;
1354 return std::make_tuple(Src, FieldWidth, std::move(Mask));
1355}
1356
1357/// Deeper than the standard analysis recursion depth to keep the numeric
1358/// bound precise through arithmetic carry chains.
1360
1361APInt getScalarMaxValue(const Value *V, unsigned Depth) {
1362 unsigned BitWidth = V->getType()->getScalarSizeInBits();
1364 if (Depth > MaxBitPackAnalysisDepth || !V->getType()->isIntegerTy())
1365 return Unknown;
1366 const APInt *C, *Amt;
1367 if (match(V, m_APInt(C)))
1368 return *C;
1369 Value *L, *R;
1370 if (match(V, m_Add(m_Value(L), m_Value(R))) ||
1371 match(V, m_Or(m_Value(L), m_Value(R))) ||
1372 match(V, m_Xor(m_Value(L), m_Value(R))))
1373 return getScalarMaxValue(L, Depth + 1)
1375 if (match(V, m_NUWSub(m_Value(L), m_Value(R))))
1376 return getScalarMaxValue(L, Depth + 1);
1377 if (match(V, m_Mul(m_Value(L), m_Value(R))))
1378 return getScalarMaxValue(L, Depth + 1)
1380 if (match(V, m_And(m_Value(L), m_Value(R))))
1381 return APIntOps::umin(getScalarMaxValue(L, Depth + 1),
1382 getScalarMaxValue(R, Depth + 1));
1383 if (match(V, m_LShr(m_Value(L), m_APInt(Amt))) && Amt->ult(BitWidth))
1384 return getScalarMaxValue(L, Depth + 1).lshr(*Amt);
1385 if (match(V, m_Shl(m_Value(L), m_APInt(Amt))) && Amt->ult(BitWidth)) {
1386 APInt LMax = getScalarMaxValue(L, Depth + 1);
1387 return LMax.getActiveBits() + Amt->getZExtValue() <= BitWidth
1388 ? LMax.shl(*Amt)
1389 : Unknown;
1390 }
1391 if (match(V, m_ZExt(m_Value(L))))
1392 return getScalarMaxValue(L, Depth + 1).zext(BitWidth);
1393 if (match(V, m_Trunc(m_Value(L)))) {
1394 APInt Max = getScalarMaxValue(L, Depth + 1);
1395 return Max.getActiveBits() <= BitWidth ? Max.trunc(BitWidth) : Unknown;
1396 }
1397 if (match(V, m_SExt(m_Value(L)))) {
1398 APInt Max = getScalarMaxValue(L, Depth + 1);
1399 return Max.isNonNegative() ? Max.zext(BitWidth) : Unknown;
1400 }
1401 Value *F;
1402 if (match(V, m_Select(m_Value(), m_Value(L), m_Value(F))))
1403 return APIntOps::umax(getScalarMaxValue(L, Depth + 1),
1404 getScalarMaxValue(F, Depth + 1));
1405 return Unknown;
1406}
1407
1408std::optional<BitPackInfo> computeBitPackInfo(unsigned BitWidth,
1409 ArrayRef<APInt> PossibleBits,
1410 ArrayRef<uint64_t> ShlAmts,
1411 ArrayRef<APInt> Masks) {
1412 unsigned NumElts = PossibleBits.size();
1413 BitPackInfo Info;
1414 Info.LShrAmts.assign(NumElts, 0);
1415 for (unsigned Idx : seq(NumElts)) {
1416 APInt Possible = PossibleBits[Idx].shl(ShlAmts[Idx]) & Masks[Idx];
1417 if (Possible.isZero())
1418 continue;
1419 unsigned Lo, W;
1420 if (!Possible.isShiftedMask(Lo, W))
1421 return std::nullopt;
1422 if (Info.FieldWidth == 0) {
1423 if (W % 8 != 0 || BitWidth % W != 0)
1424 return std::nullopt;
1425 Info.FieldWidth = W;
1426 Info.LaneOfField.assign(BitWidth / W, BitPackInfo::NoLane);
1427 }
1428 if (W != Info.FieldWidth || Lo % W != 0)
1429 return std::nullopt;
1430 unsigned Field = Lo / W;
1431 if (Info.LaneOfField[Field] != BitPackInfo::NoLane)
1432 return std::nullopt;
1433 Info.LaneOfField[Field] = Idx;
1434 Info.LShrAmts[Idx] = Lo - ShlAmts[Idx];
1435 }
1436 if (Info.FieldWidth == 0)
1437 return std::nullopt;
1438 return Info;
1439}
1440
1441SmallVector<int> getBitPackMask(const BitPackInfo &Info, unsigned NumBytes,
1442 unsigned NumElts, unsigned BytesPerLane) {
1443 unsigned BytesPerField = Info.FieldWidth / 8;
1444 SmallVector<int> Mask;
1445 for (unsigned J : seq(NumBytes)) {
1446 unsigned Lane = Info.LaneOfField[J / BytesPerField];
1447 Mask.push_back(Lane == BitPackInfo::NoLane
1448 ? (int)(NumElts * BytesPerLane)
1449 : (int)(Lane * BytesPerLane + J % BytesPerField));
1450 }
1451 return Mask;
1452}
1453
1455 unsigned ShiftWidth, unsigned &NumInsts) {
1456 NumInsts = 0;
1457 auto *VecTy = cast<FixedVectorType>(X->getType());
1458 unsigned BitWidth = VecTy->getScalarSizeInBits();
1459 assert(BitWidth % 8 == 0 &&
1460 "The byte-multiple field width divides the result bit width.");
1461 unsigned NumElts = VecTy->getNumElements();
1462 Value *Y = X;
1463 if (ShiftWidth != BitWidth) {
1464 // Compacting a zext back to its source is free, use it directly.
1465 if (auto *Z = dyn_cast<ZExtInst>(X);
1466 Z && Z->getSrcTy()->getScalarSizeInBits() == ShiftWidth)
1467 Y = Z->getOperand(0);
1468 else {
1469 Y = Builder.CreateTrunc(
1470 Y, FixedVectorType::get(IntegerType::get(X->getContext(), ShiftWidth),
1471 NumElts));
1472 ++NumInsts;
1473 }
1474 }
1475 if (Info.needsShift()) {
1477 for (uint64_t A : Info.LShrAmts)
1478 Amts.push_back(
1479 ConstantInt::get(IntegerType::get(X->getContext(), ShiftWidth), A));
1480 Y = Builder.CreateLShr(Y, ConstantVector::get(Amts));
1481 ++NumInsts;
1482 }
1483 unsigned InBytes = NumElts * (ShiftWidth / 8);
1484 auto *ByteTy = FixedVectorType::get(Builder.getInt8Ty(), InBytes);
1485 SmallVector<int> Mask =
1486 getBitPackMask(Info, BitWidth / 8, NumElts, ShiftWidth / 8);
1487 auto *IntTy = IntegerType::get(X->getContext(), BitWidth);
1488 // A plain byte reversal of the shifted lanes is a bswap.
1489 if (ShuffleVectorInst::isReverseMask(Mask, InBytes)) {
1490 NumInsts += 2;
1491 return Builder.CreateUnaryIntrinsic(Intrinsic::bswap,
1492 Builder.CreateBitCast(Y, IntTy));
1493 }
1494 // An identity byte order needs no shuffle.
1495 if (ShuffleVectorInst::isIdentityMask(Mask, InBytes)) {
1496 ++NumInsts;
1497 return Builder.CreateBitCast(Y, IntTy);
1498 }
1499 Value *Packed = Builder.CreateShuffleVector(
1500 Builder.CreateBitCast(Y, ByteTy),
1501 is_contained(Info.LaneOfField, BitPackInfo::NoLane)
1502 ? Constant::getNullValue(ByteTy)
1503 : PoisonValue::get(ByteTy),
1504 Mask);
1505 NumInsts += 3;
1506 return Builder.CreateBitCast(Packed, IntTy);
1507}
1508
1509} // namespace llvm::slpvectorizer
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Hexagon Common GEP
#define _
IRTranslator LLVM IR MI
static std::pair< Value *, APInt > getMask(Value *WideMask, unsigned Factor, ElementCount LeafValueEC)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
uint64_t IntrinsicInst * II
OptimizedStructLayoutField Field
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
Provides some synthesis utilities to produce sequences of values.
This file defines the SmallPtrSet class.
static unsigned getScalarSizeInBits(Type *Ty)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static const uint32_t IV[8]
Definition blake3_impl.h:83
Class for arbitrary precision integers.
Definition APInt.h:78
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
Definition APInt.h:230
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1057
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1560
unsigned getActiveBits() const
Compute the number of active bits in the value.
Definition APInt.h:1532
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:376
bool ult(const APInt &RHS) const
Unsigned less than comparison.
Definition APInt.h:1115
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:325
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
Definition APInt.h:506
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
Definition APInt.h:471
LLVM_ABI APInt uadd_sat(const APInt &RHS) const
Definition APInt.cpp:2074
APInt shl(unsigned shiftAmt) const
Left-shift function.
Definition APInt.h:875
LLVM_ABI APInt umul_sat(const APInt &RHS) const
Definition APInt.cpp:2115
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:302
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
Definition APInt.h:853
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
iterator end() const
Definition ArrayRef.h:130
size_t size() const
Get the array size.
Definition ArrayRef.h:141
iterator begin() const
Definition ArrayRef.h:129
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
Definition ArrayRef.h:185
const T & consume_front()
consume_front() - Returns the first element and drops it from ArrayRef.
Definition ArrayRef.h:156
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
This class represents a function call, abstracting a target machine's calling convention.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
static LLVM_ABI Constant * getBinOpAbsorber(unsigned Opcode, Type *Ty, bool AllowLHSConstant=false)
Return the absorbing element for the given binary operation, i.e.
static LLVM_ABI Constant * getBinOpIdentity(unsigned Opcode, Type *Ty, bool AllowRHSConstant=false, bool NSZ=false)
Return the identity constant for a binary opcode.
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
This instruction extracts a single (scalar) element from a VectorType value.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:843
Common base class shared among various IRBuilders.
Definition IRBuilder.h:114
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:338
An instruction for reading from memory.
Value * getPointerOperand()
This is the common base class for memset/memcpy/memmove.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
int find_first() const
Returns the index of the first set bit, -1 if none of the bits are set.
SmallBitVector & set()
bool test(unsigned Idx) const
Returns true if bit Idx is set.
int find_next(unsigned Prev) const
Returns the index of the next set bit following the "Prev" bit.
bool all() const
Returns true if all bits are set.
size_type count() const
Returns the number of bits which are set.
SmallBitVector & reset()
bool none() const
Returns true if none of the bits are set.
size_type size() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void swap(SmallVectorImpl &RHS)
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Provides information about what library functions are available for the current target.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
TargetCostKind
The kind of cost model.
@ TCK_RecipThroughput
Reciprocal throughput.
@ TCK_CodeSize
Instruction code size.
@ SK_Select
Selects elements from the corresponding lane of either source operand.
@ SK_PermuteSingleSrc
Shuffle elements of single source vector with any shuffle mask.
@ SK_PermuteTwoSrc
Merge elements from two source vectors into one with any shuffle mask.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI unsigned getIntegerBitWidth() const
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:363
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
bool hasUseList() const
Check if this Value has a use-list.
Definition Value.h:346
LLVM_ABI bool hasNUsesOrMore(unsigned N) const
Return true if this value has N uses or more.
Definition Value.cpp:155
iterator_range< use_iterator > uses()
Definition Value.h:382
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
Definition ilist_node.h:34
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const APInt & umin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be unsigned.
Definition APInt.h:2284
const APInt & umax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be unsigned.
Definition APInt.h:2289
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
BinaryOp_match< LHS, RHS, Instruction::And, true > m_c_And(const LHS &L, const RHS &R)
Matches an And with LHS and RHS in either order.
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
BinaryOp_match< LHS, RHS, Instruction::Xor > m_Xor(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
BinOpPred_match< LHS, RHS, is_right_shift_op > m_Shr(const LHS &L, const RHS &R)
Matches logical shift operations.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWSub(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::LShr > m_LShr(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Or > m_Or(const LHS &L, const RHS &R)
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
A private "module" namespace for types and utilities used by this pass.
std::optional< unsigned > getExtractIndex(const Instruction *E)
Definition SLPUtils.cpp:276
template SmallBitVector isUndefVector< true >(const Value *, const SmallBitVector &)
Value * createInsertVector(IRBuilderBase &Builder, Value *Vec, Value *V, unsigned Index, function_ref< Value *(Value *, Value *, ArrayRef< int >)> Generator)
Creates subvector insert.
Definition SLPUtils.cpp:672
bool areAllOperandsNonInsts(Value *V)
Checks if the provided value does not require scheduling.
Definition SLPUtils.cpp:456
std::optional< unsigned > getElementIndex(const Value *Inst, unsigned Offset)
Definition SLPUtils.cpp:230
bool doesInTreeUserNeedToExtract(Value *Scalar, Instruction *UserInst, TargetLibraryInfo *TLI, const TargetTransformInfo *TTI)
Definition SLPUtils.cpp:775
bool isCopyableGEPAddressVector(ArrayRef< Value * > PointerOps)
Checks if the pointers PointerOps of the gathered loads, which are not compatible in the usual sense ...
Definition SLPUtils.cpp:893
std::optional< std::tuple< Value *, unsigned, SmallVector< int > > > matchGatheredExtractedFields(ArrayRef< Value * > VL, const DataLayout &DL)
Checks if the values in VL are zero-extended sub-fields of the same wider integer scalar.
MemoryLocation getLocation(Instruction *I)
Definition SLPUtils.cpp:803
std::optional< BitPackInfo > computeBitPackInfo(unsigned BitWidth, ArrayRef< APInt > PossibleBits, ArrayRef< uint64_t > ShlAmts, ArrayRef< APInt > Masks)
Computes the bitfield packing layout from the per-lane possibly set bits of the source values,...
bool isSelectedBaseLoad(Type *ScalarTy, ArrayRef< Value * > PointerOps, const DataLayout &DL, Value *&TrueBase, Value *&FalseBase, SmallVectorImpl< Value * > &Conditions)
Checks if the loads with scalar type ScalarTy and pointer operands PointerOps are each (optionally vi...
Definition SLPUtils.cpp:821
SmallBitVector getAltInstrMask(ArrayRef< Value * > VL, Type *ScalarTy, unsigned Opcode0, unsigned Opcode1)
Definition SLPUtils.cpp:999
SmallBitVector isUndefVector(const Value *V, const SmallBitVector &UseMask)
Checks if the given value is actually an undefined constant vector.
Definition SLPUtils.cpp:725
Intrinsic::ID getMaskedDivRemIntrinsic(unsigned Opcode)
bool isUsedOutsideBlock(Value *V)
Checks if the provided value does not require scheduling.
Definition SLPUtils.cpp:467
bool doesNotNeedToSchedule(ArrayRef< Value * > VL)
Checks if the specified array of instructions does not require scheduling.
Definition SLPUtils.cpp:485
std::optional< unsigned > getInsertExtractIndex(const Value *Inst, unsigned Offset)
Definition SLPUtils.cpp:423
Value * buildBitPack(IRBuilderBase &Builder, Value *X, const BitPackInfo &Info, unsigned ShiftWidth, unsigned &NumInsts)
Builds the bitfield packing of X per the layout and the shift width.
void reorderScalars(SmallVectorImpl< Value * > &Scalars, ArrayRef< int > Mask)
Reorders the list of scalars in accordance with the given Mask.
Definition SLPUtils.cpp:309
SmallVector< int > getBitPackMask(const BitPackInfo &Info, unsigned NumBytes, unsigned NumElts, unsigned BytesPerLane)
Returns the byte shuffle mask packing the per-lane fields of the shifted lanes (BytesPerLane bytes ea...
static std::optional< std::tuple< Value *, unsigned, unsigned > > matchExtractedField(Value *V)
Checks if V is a zero-extended sub-field of a wider integer scalar.
bool allSameType(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:416
void combineOrders(MutableArrayRef< unsigned > Order, ArrayRef< unsigned > SecondaryOrder)
Fills unset elements of Order (marked with the sentinel value equal to the order size) with the corre...
Definition SLPUtils.cpp:394
bool allSameOpcode(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:258
bool isSplat(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:142
unsigned getNumElements(Type *Ty)
Definition SLPUtils.cpp:87
std::string shortBundleName(ArrayRef< Value * > VL, int Idx)
Print a short descriptor of the instruction bundle suitable for debug output.
Definition SLPUtils.cpp:104
bool isOnceUsedSeed(const Instruction *I)
Returns true if I forms a vectorizable bundle on its own and its single user does not tear the vector...
unsigned getPartNumElems(unsigned Size, unsigned NumParts)
Returns power-of-2 number of elements in a single register (part), given the total number of elements...
Definition SLPUtils.cpp:95
constexpr unsigned MaxBitPackAnalysisDepth
Deeper than the standard analysis recursion depth to keep the numeric bound precise through arithmeti...
bool isCommutableOperand(const Instruction *I, Value *ValWithUses, unsigned Op, bool IsCopyable)
Checks if the operand is commutative.
Definition SLPUtils.cpp:202
TargetTransformInfo::TargetCostKind getSLPCostKind(const Function *F)
bool isReverseOrder(ArrayRef< unsigned > Order)
Check if Order represents reverse order.
Definition SLPUtils.cpp:373
Type * getCommonGEPIndexType(ArrayRef< Value * > VL, Instruction *VL0, function_ref< bool(Value *)> IsGEPLane, const DataLayout &DL)
Returns the common type for the indices of the single-index GEP lanes of a GEP node with the main op ...
Definition SLPUtils.cpp:861
void transformScalarShuffleIndiciesToVector(unsigned VecTyNumElements, SmallVectorImpl< int > &Mask)
Definition SLPUtils.cpp:490
SmallVector< int > calculateShufflevectorMask(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:545
SmallBitVector buildUseMask(int VF, ArrayRef< int > Mask, UseMask MaskArg)
Prepares a use bitset for the given mask either for the first argument or for the second.
Definition SLPUtils.cpp:708
bool isCommutative(const Instruction *I, const Value *ValWithUses, bool IsCopyable)
Definition SLPUtils.cpp:165
template SmallBitVector isUndefVector< false >(const Value *, const SmallBitVector &)
unsigned getNumberOfPotentiallyCommutativeOps(Instruction *I)
Definition SLPUtils.cpp:220
bool allConstant(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:136
template std::optional< unsigned > getInsertExtractIndex< InsertElementInst >(const Value *, unsigned)
void inversePermutation(ArrayRef< unsigned > Indices, SmallVectorImpl< int > &Mask)
Compute the inverse permutation Mask of Indices.
Definition SLPUtils.cpp:300
bool allSameBlock(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:114
bool isReassocChainLink(const Instruction *I)
Definition SLPUtils.cpp:59
Intrinsic::ID isEquivalentIntrinsicID(Intrinsic::ID LHS, Intrinsic::ID RHS)
Checks if LHS and RHS are the same intrinsic, or one is llvm.fma and the other is llvm....
Definition SLPUtils.cpp:156
UseMask
Specifies the way the mask should be analyzed for undefs/poisonous elements in the shuffle mask.
Definition SLPUtils.h:291
@ SecondArg
The mask is expected to be for permutation of 2 vectors, check for the mask elements for the second a...
Definition SLPUtils.h:295
@ UndefsAsMask
Consider undef mask elements (-1) as placeholders for future shuffle elements and mark them as ones a...
Definition SLPUtils.h:298
@ FirstArg
The mask is expected to be for permutation of 1-2 vectors, check for the mask elements for the first ...
Definition SLPUtils.h:292
void reorderOrder(SmallVectorImpl< unsigned > &Order, ArrayRef< int > Mask, bool BottomOrder)
Reorders the given Order according to the given Mask.
Definition SLPUtils.cpp:329
static void collectNarrowedLeavesImpl(Value *V, unsigned RdxOpcode, unsigned WideBW, NarrowedChainState S, unsigned Depth, unsigned MaxDepth, SmallVectorImpl< NarrowedLeafInfo > &Leaves, SmallVectorImpl< Instruction * > &ChainInsts)
void reorderReuses(SmallVectorImpl< int > &Reuses, ArrayRef< int > Mask)
Reorders the given Reuses mask according to the given Mask.
Definition SLPUtils.cpp:319
void addMask(SmallVectorImpl< int > &Mask, ArrayRef< int > SubMask, bool ExtendingManyInputs)
Shuffles Mask in accordance with the given SubMask.
Definition SLPUtils.cpp:950
bool isSimple(Instruction *I)
Definition SLPUtils.cpp:811
Instruction * lookThroughCastRoundTrip(Value *V, bool MustBeElidable)
If V is a single-use fpext of a single-use fptrunc forming a round-trip back to the type of V,...
bool isBinOpIdentityConstant(const Value *V, unsigned Opcode)
Definition SLPUtils.cpp:43
APInt getScalarMaxValue(const Value *V, unsigned Depth)
Returns a saturating unsigned upper bound of the scalar V.
unsigned getShufflevectorNumGroups(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:505
std::optional< TargetTransformInfo::ShuffleKind > isFixedVectorShuffle(ArrayRef< Value * > VL, SmallVectorImpl< int > &Mask, AssumptionCache *AC)
Checks if the vector of instructions can be represented as a shuffle, like: x0 = extractelement <4 x ...
Definition SLPUtils.cpp:585
SmallVector< Constant * > replicateMask(ArrayRef< Constant * > Val, unsigned VF)
Replicates the given Val VF times.
unsigned getReassocCombineOpcode(unsigned Opcode)
Definition SLPUtils.cpp:48
bool isVectorLikeInstWithConstOps(Value *V)
Checks if V is one of vector-like instructions, i.e.
Definition SLPUtils.cpp:67
bool doesNotNeedToBeScheduled(Value *V)
Checks if the specified value does not require scheduling.
Definition SLPUtils.cpp:481
unsigned getNumElems(unsigned Size, unsigned PartNumElems, unsigned Part)
Returns correct remaining number of elements, considering total amount Size, (power-of-2 number) of e...
Definition SLPUtils.cpp:99
constexpr int UsesLimit
Limit of the number of uses for potentially transformed instructions/values, used in checks to avoid ...
Definition SLPUtils.h:50
void collectNarrowedLeaves(Value *V, unsigned RdxOpcode, unsigned WideBW, unsigned MaxDepth, SmallVectorImpl< NarrowedLeafInfo > &Leaves, SmallVectorImpl< Instruction * > &ChainInsts)
Recursively collects the narrow leaves of the widened reduction value V.
bool isRepeatedNonIdentityClusteredMask(ArrayRef< int > Mask, unsigned Sz)
Checks if the given mask is a "clustered" mask with the same clusters of size Sz, which are not ident...
Definition SLPUtils.cpp:382
bool isConstant(Value *V)
Definition SLPUtils.cpp:39
static bool isNonProfitableIndex(const Instruction *I)
Returns true if I is a part of a single-use chain, computing an address, which does not pay off the v...
Value * createExtractVector(IRBuilderBase &Builder, Value *Vec, unsigned SubVecVF, unsigned Index)
Generates subvector extract.
Definition SLPUtils.cpp:701
template std::optional< unsigned > getInsertExtractIndex< ExtractElementInst >(const Value *, unsigned)
void fixupOrderingIndices(MutableArrayRef< unsigned > Order)
Order may have elements assigned special value (size) which is out of bounds.
Definition SLPUtils.cpp:975
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
constexpr auto not_equal_to(T &&Arg)
Functor variant of std::not_equal_to that can be used as a UnaryPredicate in functional algorithms li...
Definition STLExtras.h:2196
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
LLVM_ABI Intrinsic::ID getVectorIntrinsicIDForCall(const CallInst *CI, const TargetLibraryInfo *TLI)
Returns intrinsic ID for call.
@ Unknown
Not known to have no common set bits.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto accumulate(R &&Range, E &&Init)
Wrapper for std::accumulate.
Definition STLExtras.h:1718
constexpr from_range_t from_range
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool isVectorizedTy(Type *Ty)
Returns true if Ty is a vector type or a struct of vector types where all vector types share the same...
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
Definition bit.h:362
auto make_isa_range(RangeT &&Range)
Return a range over Range containing only elements for which isa<T> holds, casting each of them to T.
Definition STLExtras.h:567
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
constexpr unsigned MaxAnalysisRecursionDepth
ElementCount getVectorizedTypeVF(Type *Ty)
Returns the number of vector elements for a vectorized type.
auto find_if_not(R &&Range, UnaryPredicate P)
Definition STLExtras.h:1793
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1769
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
Definition STLExtras.h:552
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...
Definition Casting.h:547
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr int PoisonMaskElem
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
TargetTransformInfo TTI
DWARFExpression::Operation Op
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
LLVM_ABI bool isGuaranteedNotToBePoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Returns true if V cannot be poison, but may be undef.
LLVM_ABI bool mayHaveNonDefUseDependency(const Instruction &I)
Returns true if the result or effects of the given instructions I depend values not reachable through...
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
Definition Casting.h:866
Description of a bitfield packing of vector lanes into a scalar value: every lane contributes a disjo...
Definition SLPUtils.h:466
static constexpr unsigned NoLane
Definition SLPUtils.h:467
SmallVector< uint64_t, 8 > LShrAmts
Per-lane right-shift amounts bringing the field content to the low bits.
Definition SLPUtils.h:472