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"
17#include "llvm/IR/Constants.h"
18#include "llvm/IR/DataLayout.h"
20#include "llvm/IR/IRBuilder.h"
27
28#include <algorithm>
29#include <numeric>
30#include <string>
31#include <type_traits>
32
33using namespace llvm;
34using namespace llvm::PatternMatch;
35
36namespace llvm::slpvectorizer {
37
41
42bool isBinOpIdentityConstant(const Value *V, unsigned Opcode) {
43 const auto *CI = dyn_cast<ConstantInt>(V);
44 return CI && ConstantExpr::getBinOpIdentity(Opcode, CI->getType()) == CI;
45}
46
47unsigned getReassocCombineOpcode(unsigned Opcode) {
48 switch (Opcode) {
49 case Instruction::Sub:
50 return Instruction::Add;
51 case Instruction::FSub:
52 return Instruction::FAdd;
53 default:
54 return Opcode;
55 }
56}
57
59 if (I->getOpcode() == Instruction::Sub)
60 return true;
61 if (I->getOpcode() == Instruction::FSub)
62 return I->hasAllowReassoc();
63 return I->isAssociative();
64}
65
67 auto *I = dyn_cast<Instruction>(V);
68 // Non-instructions are vector-like only if they are undef.
69 if (!I)
70 return isa<UndefValue>(V);
71 switch (I->getOpcode()) {
72 case Instruction::ExtractValue:
73 case Instruction::InsertValue:
74 return true;
75 case Instruction::ExtractElement:
76 return isa<FixedVectorType>(I->getOperand(0)->getType()) &&
77 isConstant(I->getOperand(1));
78 case Instruction::InsertElement:
79 return isa<FixedVectorType>(I->getOperand(0)->getType()) &&
80 isConstant(I->getOperand(2));
81 default:
82 return false;
83 }
84}
85
86unsigned getNumElements(Type *Ty) {
88 "ScalableVectorType is not supported.");
89 if (isVectorizedTy(Ty))
91 return 1;
92}
93
94unsigned getPartNumElems(unsigned Size, unsigned NumParts) {
95 return std::min<unsigned>(Size, bit_ceil(divideCeil(Size, NumParts)));
96}
97
98unsigned getNumElems(unsigned Size, unsigned PartNumElems, unsigned Part) {
99 return std::min<unsigned>(PartNumElems, Size - Part * PartNumElems);
100}
101
102#if !defined(NDEBUG)
103std::string shortBundleName(ArrayRef<Value *> VL, int Idx) {
104 std::string Result;
105 raw_string_ostream OS(Result);
106 if (Idx >= 0)
107 OS << "Idx: " << Idx << ", ";
108 OS << "n=" << VL.size() << " [" << *VL.front() << ", ..]";
109 return Result;
110}
111#endif
112
114 auto *It = find_if(VL, IsaPred<Instruction>);
115 if (It == VL.end())
116 return false;
119 return true;
120
121 BasicBlock *BB = I0->getParent();
122 for (Value *V : iterator_range(It, VL.end())) {
123 if (isa<PoisonValue>(V))
124 continue;
125 auto *II = dyn_cast<Instruction>(V);
126 if (!II)
127 return false;
128
129 if (BB != II->getParent())
130 return false;
131 }
132 return true;
133}
134
136 // Constant expressions and globals can't be vectorized like normal integer/FP
137 // constants.
138 return all_of(VL, isConstant);
139}
140
142 Value *FirstNonUndef = nullptr;
143 for (Value *V : VL) {
144 if (isa<UndefValue>(V))
145 continue;
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) &&
461 all_of(I->operands(), [I](Value *V) {
462 auto *IO = dyn_cast<Instruction>(V);
463 if (!IO)
464 return true;
465 return isa<PHINode>(IO) || IO->getParent() != I->getParent();
466 });
467}
468
470 auto *I = dyn_cast<Instruction>(V);
471 if (!I)
472 return true;
473 // Limits the number of uses to save compile time.
474 return !I->mayReadOrWriteMemory() && !I->hasNUsesOrMore(UsesLimit) &&
475 all_of(I->users(), [I](User *U) {
476 auto *IU = dyn_cast<Instruction>(U);
477 if (!IU)
478 return true;
479 return IU->getParent() != I->getParent() || isa<PHINode>(IU);
480 });
481}
482
486
491
492void transformScalarShuffleIndiciesToVector(unsigned VecTyNumElements,
493 SmallVectorImpl<int> &Mask) {
494 // The ShuffleBuilder implementation use shufflevector to splat an "element".
495 // But the element have different meaning for SLP (scalar) and REVEC
496 // (vector). We need to expand Mask into masks which shufflevector can use
497 // directly.
498 SmallVector<int> NewMask(Mask.size() * VecTyNumElements);
499 for (unsigned I : seq<unsigned>(Mask.size()))
500 for (auto [J, MaskV] : enumerate(MutableArrayRef(NewMask).slice(
501 I * VecTyNumElements, VecTyNumElements)))
502 MaskV = Mask[I] == PoisonMaskElem ? PoisonMaskElem
503 : Mask[I] * VecTyNumElements + J;
504 Mask.swap(NewMask);
505}
506
508 if (VL.empty())
509 return 0;
511 return 0;
512 auto *SV = cast<ShuffleVectorInst>(VL.front());
513 unsigned SVNumElements =
514 cast<FixedVectorType>(SV->getOperand(0)->getType())->getNumElements();
515 unsigned ShuffleMaskSize = SV->getShuffleMask().size();
516 if (SVNumElements % ShuffleMaskSize != 0)
517 return 0;
518 unsigned GroupSize = SVNumElements / ShuffleMaskSize;
519 if (GroupSize == 0 || (VL.size() % GroupSize) != 0)
520 return 0;
521 unsigned NumGroup = 0;
522 for (size_t I = 0, E = VL.size(); I != E; I += GroupSize) {
523 auto *SV = cast<ShuffleVectorInst>(VL[I]);
524 Value *Src = SV->getOperand(0);
525 ArrayRef<Value *> Group = VL.slice(I, GroupSize);
526 SmallBitVector ExpectedIndex(GroupSize);
527 if (!all_of(Group, [&](Value *V) {
528 auto *SV = cast<ShuffleVectorInst>(V);
529 // From the same source.
530 if (SV->getOperand(0) != Src)
531 return false;
532 int Index;
533 if (!SV->isExtractSubvectorMask(Index))
534 return false;
535 ExpectedIndex.set(Index / ShuffleMaskSize);
536 return true;
537 }))
538 return 0;
539 if (!ExpectedIndex.all())
540 return 0;
541 ++NumGroup;
542 }
543 assert(NumGroup == (VL.size() / GroupSize) && "Unexpected number of groups");
544 return NumGroup;
545}
546
548 assert(getShufflevectorNumGroups(VL) && "Not supported shufflevector usage.");
549 auto *SV = cast<ShuffleVectorInst>(VL.front());
550 unsigned SVNumElements =
551 cast<FixedVectorType>(SV->getOperand(0)->getType())->getNumElements();
552 SmallVector<int> Mask;
553 unsigned AccumulateLength = 0;
554 for (Value *V : VL) {
555 auto *SV = cast<ShuffleVectorInst>(V);
556 for (int M : SV->getShuffleMask())
557 Mask.push_back(M == PoisonMaskElem ? PoisonMaskElem
558 : AccumulateLength + M);
559 AccumulateLength += SVNumElements;
560 }
561 return Mask;
562}
563
564/// Checks if the vector of instructions can be represented as a shuffle, like:
565/// %x0 = extractelement <4 x i8> %x, i32 0
566/// %x3 = extractelement <4 x i8> %x, i32 3
567/// %y1 = extractelement <4 x i8> %y, i32 1
568/// %y2 = extractelement <4 x i8> %y, i32 2
569/// %x0x0 = mul i8 %x0, %x0
570/// %x3x3 = mul i8 %x3, %x3
571/// %y1y1 = mul i8 %y1, %y1
572/// %y2y2 = mul i8 %y2, %y2
573/// %ins1 = insertelement <4 x i8> poison, i8 %x0x0, i32 0
574/// %ins2 = insertelement <4 x i8> %ins1, i8 %x3x3, i32 1
575/// %ins3 = insertelement <4 x i8> %ins2, i8 %y1y1, i32 2
576/// %ins4 = insertelement <4 x i8> %ins3, i8 %y2y2, i32 3
577/// ret <4 x i8> %ins4
578/// can be transformed into:
579/// %1 = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 3, i32 5,
580/// i32 6>
581/// %2 = mul <4 x i8> %1, %1
582/// ret <4 x i8> %2
583/// Mask will return the Shuffle Mask equivalent to the extracted elements.
584/// TODO: Can we split off and reuse the shuffle mask detection from
585/// ShuffleVectorInst/getShuffleCost?
586std::optional<TargetTransformInfo::ShuffleKind>
588 AssumptionCache *AC) {
589 const auto *It = find_if(VL, IsaPred<ExtractElementInst>);
590 if (It == VL.end())
591 return std::nullopt;
592 unsigned Size = accumulate(VL, 0u, [](unsigned S, Value *V) {
593 auto *EI = dyn_cast<ExtractElementInst>(V);
594 if (!EI)
595 return S;
596 auto *VTy = dyn_cast<FixedVectorType>(EI->getVectorOperandType());
597 if (!VTy)
598 return S;
599 return std::max(S, VTy->getNumElements());
600 });
601
602 Value *Vec1 = nullptr;
603 Value *Vec2 = nullptr;
604 bool HasNonUndefVec = any_of(VL, [&](Value *V) {
605 auto *EE = dyn_cast<ExtractElementInst>(V);
606 if (!EE)
607 return false;
608 Value *Vec = EE->getVectorOperand();
609 if (isa<UndefValue>(Vec))
610 return false;
611 return isGuaranteedNotToBePoison(Vec, AC);
612 });
613 enum ShuffleMode { Unknown, Select, Permute };
614 ShuffleMode CommonShuffleMode = Unknown;
615 Mask.assign(VL.size(), PoisonMaskElem);
616 for (unsigned I = 0, E = VL.size(); I < E; ++I) {
617 // Undef, or a copyable lane modeled on an extract main op, can be
618 // represented as an undef element in a vector.
619 if (isa<UndefValue>(VL[I]))
620 continue;
621 auto *EI = dyn_cast<ExtractElementInst>(VL[I]);
622 if (!EI)
623 continue;
624 if (isa<ScalableVectorType>(EI->getVectorOperandType()))
625 return std::nullopt;
626 auto *Vec = EI->getVectorOperand();
627 // We can extractelement from undef or poison vector.
629 continue;
630 // All vector operands must have the same number of vector elements.
631 if (isa<UndefValue>(Vec)) {
632 Mask[I] = I;
633 } else {
634 if (isa<UndefValue>(EI->getIndexOperand()))
635 continue;
636 auto *Idx = dyn_cast<ConstantInt>(EI->getIndexOperand());
637 if (!Idx)
638 return std::nullopt;
639 // Undefined behavior if Idx is negative or >= Size.
640 if (Idx->getValue().uge(Size))
641 continue;
642 unsigned IntIdx = Idx->getValue().getZExtValue();
643 Mask[I] = IntIdx;
644 }
645 if (isUndefVector(Vec).all() && HasNonUndefVec)
646 continue;
647 // For correct shuffling we have to have at most 2 different vector operands
648 // in all extractelement instructions.
649 if (!Vec1 || Vec1 == Vec) {
650 Vec1 = Vec;
651 } else if (!Vec2 || Vec2 == Vec) {
652 Vec2 = Vec;
653 Mask[I] += Size;
654 } else {
655 return std::nullopt;
656 }
657 if (CommonShuffleMode == Permute)
658 continue;
659 // If the extract index is not the same as the operation number, it is a
660 // permutation.
661 if (Mask[I] % Size != I) {
662 CommonShuffleMode = Permute;
663 continue;
664 }
665 CommonShuffleMode = Select;
666 }
667 // If we're not crossing lanes in different vectors, consider it as blending.
668 if (CommonShuffleMode == Select && Vec2)
670 // If Vec2 was never used, we have a permutation of a single vector, otherwise
671 // we have permutation of 2 vectors.
674}
675
677 IRBuilderBase &Builder, Value *Vec, Value *V, unsigned Index,
678 function_ref<Value *(Value *, Value *, ArrayRef<int>)> Generator) {
679 if (isa<PoisonValue>(Vec) && isa<PoisonValue>(V))
680 return Vec;
681 const unsigned SubVecVF = getNumElements(V->getType());
682 // Create shuffle, insertvector requires that index is multiple of
683 // the subvector length.
684 const unsigned VecVF = getNumElements(Vec->getType());
685 SmallVector<int> Mask(VecVF, PoisonMaskElem);
686 if (isa<PoisonValue>(Vec)) {
687 auto *Begin = std::next(Mask.begin(), Index);
688 std::iota(Begin, std::next(Begin, SubVecVF), 0);
689 Vec = Builder.CreateShuffleVector(V, Mask);
690 return Vec;
691 }
692 std::iota(Mask.begin(), Mask.end(), 0);
693 std::iota(std::next(Mask.begin(), Index),
694 std::next(Mask.begin(), Index + SubVecVF), VecVF);
695 if (Generator)
696 return Generator(Vec, V, Mask);
697 // 1. Resize V to the size of Vec.
698 SmallVector<int> ResizeMask(VecVF, PoisonMaskElem);
699 std::iota(ResizeMask.begin(), std::next(ResizeMask.begin(), SubVecVF), 0);
700 V = Builder.CreateShuffleVector(V, ResizeMask);
701 // 2. Insert V into Vec.
702 return Builder.CreateShuffleVector(Vec, V, Mask);
703}
704
706 unsigned SubVecVF, unsigned Index) {
707 SmallVector<int> Mask(SubVecVF, PoisonMaskElem);
708 std::iota(Mask.begin(), Mask.end(), Index);
709 return Builder.CreateShuffleVector(Vec, Mask);
710}
711
713 SmallBitVector UseMask(VF, true);
714 for (auto [Idx, Value] : enumerate(Mask)) {
715 if (Value == PoisonMaskElem) {
716 if (MaskArg == UseMask::UndefsAsMask)
717 UseMask.reset(Idx);
718 continue;
719 }
720 if (MaskArg == UseMask::FirstArg && Value < VF)
721 UseMask.reset(Value);
722 else if (MaskArg == UseMask::SecondArg && Value >= VF)
723 UseMask.reset(Value - VF);
724 }
725 return UseMask;
726}
727
728template <bool IsPoisonOnly>
730 SmallBitVector Res(UseMask.empty() ? 1 : UseMask.size(), true);
731 using T = std::conditional_t<IsPoisonOnly, PoisonValue, UndefValue>;
732 if (isa<T>(V))
733 return Res;
734 auto *VecTy = dyn_cast<FixedVectorType>(V->getType());
735 if (!VecTy)
736 return Res.reset();
737 auto *C = dyn_cast<Constant>(V);
738 if (!C) {
739 if (!UseMask.empty()) {
740 const Value *Base = V;
741 while (auto *II = dyn_cast<InsertElementInst>(Base)) {
742 Base = II->getOperand(0);
743 if (isa<T>(II->getOperand(1)))
744 continue;
745 std::optional<unsigned> Idx = getElementIndex(II);
746 if (!Idx) {
747 Res.reset();
748 return Res;
749 }
750 if (*Idx < UseMask.size() && !UseMask.test(*Idx))
751 Res.reset(*Idx);
752 }
753 // TODO: Add analysis for shuffles here too.
754 if (V == Base) {
755 Res.reset();
756 } else {
757 SmallBitVector SubMask(UseMask.size(), false);
758 Res &= isUndefVector<IsPoisonOnly>(Base, SubMask);
759 }
760 } else {
761 Res.reset();
762 }
763 return Res;
764 }
765 for (unsigned I = 0, E = VecTy->getNumElements(); I != E; ++I) {
766 if (Constant *Elem = C->getAggregateElement(I))
767 if (!isa<T>(Elem) &&
768 (UseMask.empty() || (I < UseMask.size() && !UseMask.test(I))))
769 Res.reset(I);
770 }
771 return Res;
772}
773
775 const SmallBitVector &);
777 const SmallBitVector &);
778
781 const TargetTransformInfo *TTI) {
782 if (!UserInst)
783 return false;
784 unsigned Opcode = UserInst->getOpcode();
785 switch (Opcode) {
786 case Instruction::Load: {
787 LoadInst *LI = cast<LoadInst>(UserInst);
788 return (LI->getPointerOperand() == Scalar);
789 }
790 case Instruction::Store: {
791 StoreInst *SI = cast<StoreInst>(UserInst);
792 return (SI->getPointerOperand() == Scalar);
793 }
794 case Instruction::Call: {
795 CallInst *CI = cast<CallInst>(UserInst);
797 return any_of(enumerate(CI->args()), [&](auto &&Arg) {
798 return isVectorIntrinsicWithScalarOpAtArg(ID, Arg.index(), TTI) &&
799 Arg.value().get() == Scalar;
800 });
801 }
802 default:
803 return false;
804 }
805}
806
814
816 if (LoadInst *LI = dyn_cast<LoadInst>(I))
817 return LI->isSimple();
819 return SI->isSimple();
821 return !MI->isVolatile();
822 return true;
823}
824
825bool isSelectedBaseLoad(Type *ScalarTy, ArrayRef<Value *> PointerOps,
826 const DataLayout &DL, Value *&TrueBase,
827 Value *&FalseBase,
828 SmallVectorImpl<Value *> &Conditions) {
829 TrueBase = nullptr;
830 FalseBase = nullptr;
831 uint64_t ScalarSize = DL.getTypeStoreSize(ScalarTy);
832 Conditions.assign(PointerOps.size(), nullptr);
833 for (auto [Idx, P] : enumerate(PointerOps)) {
834 Value *Base = P;
835 uint64_t Offset = 0;
836 if (auto *GEP = dyn_cast<GetElementPtrInst>(P)) {
837 APInt OffsetAP(DL.getIndexTypeSizeInBits(GEP->getType()), 0);
838 if (!GEP->accumulateConstantOffset(DL, OffsetAP) || OffsetAP.isNegative())
839 return false;
840 Offset = OffsetAP.getZExtValue();
841 Base = GEP->getPointerOperand();
842 }
843 auto *Sel = dyn_cast<SelectInst>(Base);
844 if (!Sel)
845 return false;
846 Value *T = Sel->getTrueValue();
847 Value *F = Sel->getFalseValue();
848 if (!TrueBase) {
849 if (T == F)
850 return false;
851 TrueBase = T;
852 FalseBase = F;
853 } else if (TrueBase != T || FalseBase != F) {
854 return false;
855 }
856 // Lane Idx must be at exactly Base + Idx * sizeof(ScalarTy); codegen reads
857 // contiguously from TrueBase/FalseBase starting at lane 0.
858 if (Offset != static_cast<uint64_t>(Idx) * ScalarSize)
859 return false;
860 Conditions[Idx] = Sel->getCondition();
861 }
862 return TrueBase != nullptr;
863}
864
866 bool ExtendingManyInputs) {
867 if (SubMask.empty())
868 return;
869 assert(
870 (!ExtendingManyInputs || SubMask.size() > Mask.size() ||
871 // Check if input scalars were extended to match the size of other node.
872 (SubMask.size() == Mask.size() && Mask.back() == PoisonMaskElem)) &&
873 "SubMask with many inputs support must be larger than the mask.");
874 if (Mask.empty()) {
875 Mask.append(SubMask.begin(), SubMask.end());
876 return;
877 }
878 SmallVector<int> NewMask(SubMask.size(), PoisonMaskElem);
879 int TermValue = std::min(Mask.size(), SubMask.size());
880 for (int I = 0, E = SubMask.size(); I < E; ++I) {
881 if (SubMask[I] == PoisonMaskElem ||
882 (!ExtendingManyInputs &&
883 (SubMask[I] >= TermValue || Mask[SubMask[I]] >= TermValue)))
884 continue;
885 NewMask[I] = Mask[SubMask[I]];
886 }
887 Mask.swap(NewMask);
888}
889
891 const size_t Sz = Order.size();
892 SmallBitVector UnusedIndices(Sz, /*t=*/true);
893 SmallBitVector MaskedIndices(Sz);
894 for (unsigned I = 0; I < Sz; ++I) {
895 if (Order[I] < Sz)
896 UnusedIndices.reset(Order[I]);
897 else
898 MaskedIndices.set(I);
899 }
900 if (MaskedIndices.none())
901 return;
902 assert(UnusedIndices.count() == MaskedIndices.count() &&
903 "Non-synced masked/available indices.");
904 int Idx = UnusedIndices.find_first();
905 int MIdx = MaskedIndices.find_first();
906 while (MIdx >= 0) {
907 assert(Idx >= 0 && "Indices must be synced.");
908 Order[MIdx] = Idx;
909 Idx = UnusedIndices.find_next(Idx);
910 MIdx = MaskedIndices.find_next(MIdx);
911 }
912}
913
915 unsigned Opcode0, unsigned Opcode1) {
916 unsigned ScalarTyNumElements = getNumElements(ScalarTy);
917 SmallBitVector OpcodeMask(VL.size() * ScalarTyNumElements, false);
918 for (unsigned Lane : seq<unsigned>(VL.size())) {
919 if (isa<PoisonValue>(VL[Lane]))
920 continue;
921 if (cast<Instruction>(VL[Lane])->getOpcode() == Opcode1)
922 OpcodeMask.set(Lane * ScalarTyNumElements,
923 Lane * ScalarTyNumElements + ScalarTyNumElements);
924 }
925 return OpcodeMask;
926}
927
929 assert(none_of(Val, [](Constant *C) { return C->getType()->isVectorTy(); }) &&
930 "Expected scalar constants.");
931 SmallVector<Constant *> NewVal(Val.size() * VF);
932 for (auto [I, V] : enumerate(Val))
933 std::fill_n(NewVal.begin() + I * VF, VF, V);
934 return NewVal;
935}
936
938 switch (Opcode) {
939 case Instruction::UDiv:
940 return Intrinsic::masked_udiv;
941 case Instruction::SDiv:
942 return Intrinsic::masked_sdiv;
943 case Instruction::URem:
944 return Intrinsic::masked_urem;
945 case Instruction::SRem:
946 return Intrinsic::masked_srem;
947 default:
948 llvm_unreachable("Unexpected opcode");
949 }
950}
951
952/// Returns true if \p I is a part of a single-use chain, computing an address,
953/// which does not pay off the vectorization: a constant table is accessed by a
954/// gather, while the indices, unrelated between the lanes, require a full
955/// buildvector, unlike the ones, shifted by a constant from a common base.
956static bool isNonProfitableIndex(const Instruction *I) {
957 constexpr unsigned MaxIndexChainLength = 3;
958 // A constant shift of a common base is a cheap buildvector, while the loads
959 // are vectorized together with the indices, computed from them.
960 auto IsProfitableOperand = [](const Value *V) {
961 if (isa<Constant>(V))
962 return true;
963 if (const auto *Cast = dyn_cast<CastInst>(V); Cast && Cast->hasOneUse())
964 V = Cast->getOperand(0);
965 return isa<LoadInst>(V);
966 };
967 const User *U = I->user_back();
968 for ([[maybe_unused]] unsigned _ : seq<unsigned>(MaxIndexChainLength)) {
969 if (const auto *GEP = dyn_cast<GetElementPtrInst>(U))
970 return isa<Constant>(GEP->getPointerOperand()) ||
971 none_of(I->operand_values(), IsProfitableOperand);
972 if (!isa<Instruction>(U) || !U->hasOneUse())
973 return false;
974 U = U->user_back();
975 }
976 return false;
977}
978
980 if (!I->hasOneUse() || isNonProfitableIndex(I))
981 return false;
982 // The operation with the identity or the absorbing constant is folded away
983 // before the codegen, the vector node only repacks the lanes.
984 if (const auto *BO = dyn_cast<BinaryOperator>(I)) {
985 unsigned Opcode = BO->getOpcode();
986 Type *Ty = BO->getType();
987 for (unsigned Idx : seq<unsigned>(2)) {
988 const auto *C = dyn_cast<Constant>(BO->getOperand(Idx));
990 Opcode, Ty, /*AllowRHSConstant=*/Idx == 1) ||
992 Opcode, Ty, /*AllowLHSConstant=*/Idx == 0)))
993 return false;
994 }
995 }
996 const User *U = I->user_back();
999 if (isa<CastInst>(I))
1000 return !isa<FPToSIInst, FPToUIInst>(I) &&
1001 (!isa<CastInst>(U) || U->hasOneUse());
1003 I);
1004}
1005
1006Instruction *lookThroughCastRoundTrip(Value *V, bool MustBeElidable) {
1007 auto *Wide = dyn_cast<FPExtInst>(V);
1008 if (!Wide || !Wide->hasOneUse())
1009 return nullptr;
1010 auto *Narrow = dyn_cast<FPTruncInst>(Wide->getOperand(0));
1011 if (!Narrow || !Narrow->hasOneUse())
1012 return nullptr;
1013 Value *Src = Narrow->getOperand(0);
1014 if (!isa<Instruction>(Src) || Src->getType() != Wide->getType())
1015 return nullptr;
1016 if (MustBeElidable && !(Wide->hasAllowContract() && Wide->hasNoNaNs() &&
1017 Wide->hasNoInfs() && Narrow->hasAllowContract()))
1018 return nullptr;
1019 return Narrow;
1020}
1021
1022namespace {
1023
1024/// Shifts and the mask accumulated from the narrow ops on the current path:
1025/// the shifts above and at the narrow level, the bitwidth of the narrow ops
1026/// (0 if none) and the mask from the absorbed narrow ands.
1027struct NarrowedChainState {
1028 unsigned Shift = 0;
1029 unsigned NarrowShift = 0;
1030 unsigned NarrowBW = 0;
1031 APInt NarrowMask = APInt(1, 0);
1032
1033 /// The mask for the absorbed narrow ops in the leaf type, applied before
1034 /// widening and shifting; all-ones if nothing was absorbed.
1035 APInt getMask(unsigned LeafBW) const {
1036 if (NarrowBW == 0)
1037 return APInt::getAllOnes(LeafBW);
1038 return (NarrowMask & (APInt::getAllOnes(NarrowBW) << NarrowShift))
1039 .lshr(NarrowShift)
1040 .trunc(LeafBW);
1041 }
1042};
1043
1044} // namespace
1045
1046static void
1047collectNarrowedLeavesImpl(Value *V, unsigned RdxOpcode, unsigned WideBW,
1048 NarrowedChainState S, unsigned Depth,
1049 unsigned MaxDepth,
1051 SmallVectorImpl<Instruction *> &ChainInsts) {
1052 if (Depth < MaxDepth) {
1053 if (auto *Z = dyn_cast<ZExtInst>(V);
1054 Z && Z->getSrcTy()->isIntegerTy() && !Z->getSrcTy()->isIntegerTy(1)) {
1055 ChainInsts.push_back(Z);
1056 return collectNarrowedLeavesImpl(Z->getOperand(0), RdxOpcode, WideBW, S,
1057 Depth + 1, MaxDepth, Leaves, ChainInsts);
1058 }
1059 if (auto *BO = dyn_cast<BinaryOperator>(V)) {
1060 if (BO->getOpcode() == RdxOpcode) {
1061 ChainInsts.push_back(BO);
1062 collectNarrowedLeavesImpl(BO->getOperand(0), RdxOpcode, WideBW, S,
1063 Depth + 1, MaxDepth, Leaves, ChainInsts);
1064 collectNarrowedLeavesImpl(BO->getOperand(1), RdxOpcode, WideBW, S,
1065 Depth + 1, MaxDepth, Leaves, ChainInsts);
1066 return;
1067 }
1068 const APInt *Amt;
1069 unsigned BW = V->getType()->getScalarSizeInBits();
1070 auto *Z = dyn_cast<ZExtInst>(BO->getOperand(0));
1071 if (BO->getOpcode() == Instruction::Shl && Z && S.NarrowBW == 0 &&
1072 match(BO->getOperand(1), m_APInt(Amt)) && Amt->ult(BW) &&
1073 Z->getSrcTy()->isIntegerTy() && !Z->getSrcTy()->isIntegerTy(1) &&
1074 (BW == WideBW ||
1075 Z->getSrcTy()->getIntegerBitWidth() + Amt->getZExtValue() <= BW) &&
1076 S.Shift + Amt->getZExtValue() < WideBW) {
1077 ChainInsts.push_back(BO);
1078 ChainInsts.push_back(Z);
1079 S.Shift += Amt->getZExtValue();
1080 return collectNarrowedLeavesImpl(Z->getOperand(0), RdxOpcode, WideBW, S,
1081 Depth + 1, MaxDepth, Leaves,
1082 ChainInsts);
1083 }
1084 // Narrow shls fold into the shift and narrow ands into the mask; the
1085 // mask clears the bits the shls shift out. Only same-width ops compose
1086 // on one path, and the combined shift must stay a valid shift amount in
1087 // both types.
1088 if (BW < WideBW && (S.NarrowBW == 0 || BW == S.NarrowBW)) {
1089 if (BO->getOpcode() == Instruction::Shl &&
1090 match(BO->getOperand(1), m_APInt(Amt)) && Amt->ult(BW) &&
1091 S.NarrowShift + Amt->getZExtValue() < BW &&
1092 S.Shift + S.NarrowShift + Amt->getZExtValue() < WideBW) {
1093 ChainInsts.push_back(BO);
1094 if (BO->hasNoUnsignedWrap() && S.NarrowBW == 0) {
1095 S.Shift += Amt->getZExtValue();
1096 // Lossless shls shift out only known-zero bits; record them as
1097 // the mask so matching lanes can form a splat.
1098 S.NarrowBW = BW;
1099 S.NarrowMask = APInt::getLowBitsSet(BW, BW - Amt->getZExtValue());
1100 } else {
1101 if (S.NarrowBW == 0) {
1102 S.NarrowBW = BW;
1103 S.NarrowMask = APInt::getAllOnes(BW);
1104 }
1105 S.NarrowShift += Amt->getZExtValue();
1106 }
1107 return collectNarrowedLeavesImpl(BO->getOperand(0), RdxOpcode, WideBW,
1108 S, Depth + 1, MaxDepth, Leaves,
1109 ChainInsts);
1110 }
1111 Value *X;
1112 if (match(BO, m_c_And(m_Value(X), m_APInt(Amt)))) {
1113 ChainInsts.push_back(BO);
1114 if (S.NarrowBW == 0) {
1115 S.NarrowBW = BW;
1116 S.NarrowMask = APInt::getAllOnes(BW);
1117 }
1118 S.NarrowMask &= *Amt << S.NarrowShift;
1119 return collectNarrowedLeavesImpl(X, RdxOpcode, WideBW, S, Depth + 1,
1120 MaxDepth, Leaves, ChainInsts);
1121 }
1122 }
1123 }
1124 }
1125 Leaves.emplace_back(V, S.Shift + S.NarrowShift,
1126 S.getMask(V->getType()->getScalarSizeInBits()));
1127}
1128
1129void collectNarrowedLeaves(Value *V, unsigned RdxOpcode, unsigned WideBW,
1130 unsigned MaxDepth,
1132 SmallVectorImpl<Instruction *> &ChainInsts) {
1133 collectNarrowedLeavesImpl(V, RdxOpcode, WideBW, NarrowedChainState(),
1134 /*Depth=*/0, MaxDepth, Leaves, ChainInsts);
1135}
1136
1138 assert(F && "Expected function.");
1139 return F->hasOptSize() ? TTI::TCK_CodeSize : TTI::TCK_RecipThroughput;
1140}
1141
1142} // 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")
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
#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.
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:231
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1561
bool ult(const APInt &RHS) const
Unsigned less than comparison.
Definition APInt.h:1116
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:326
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:303
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.
This is an important base class in LLVM.
Definition Constant.h:43
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
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.
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...
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.
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
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
bool hasUseList() const
Check if this Value has a use-list.
Definition Value.h:344
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:380
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.
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.
bool match(Val *V, const Pattern &P)
auto m_Value()
Match an arbitrary value and ignore it.
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:676
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:779
MemoryLocation getLocation(Instruction *I)
Definition SLPUtils.cpp:807
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:825
SmallBitVector getAltInstrMask(ArrayRef< Value * > VL, Type *ScalarTy, unsigned Opcode0, unsigned Opcode1)
Definition SLPUtils.cpp:914
SmallBitVector isUndefVector(const Value *V, const SmallBitVector &UseMask)
Checks if the given value is actually an undefined constant vector.
Definition SLPUtils.cpp:729
Intrinsic::ID getMaskedDivRemIntrinsic(unsigned Opcode)
Definition SLPUtils.cpp:937
bool isUsedOutsideBlock(Value *V)
Checks if the provided value does not require scheduling.
Definition SLPUtils.cpp:469
bool doesNotNeedToSchedule(ArrayRef< Value * > VL)
Checks if the specified array of instructions does not require scheduling.
Definition SLPUtils.cpp:487
std::optional< unsigned > getInsertExtractIndex(const Value *Inst, unsigned Offset)
Definition SLPUtils.cpp:423
void reorderScalars(SmallVectorImpl< Value * > &Scalars, ArrayRef< int > Mask)
Reorders the list of scalars in accordance with the given Mask.
Definition SLPUtils.cpp:309
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:141
unsigned getNumElements(Type *Ty)
Definition SLPUtils.cpp:86
std::string shortBundleName(ArrayRef< Value * > VL, int Idx)
Print a short descriptor of the instruction bundle suitable for debug output.
Definition SLPUtils.cpp:103
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...
Definition SLPUtils.cpp:979
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:94
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
void transformScalarShuffleIndiciesToVector(unsigned VecTyNumElements, SmallVectorImpl< int > &Mask)
Definition SLPUtils.cpp:492
SmallVector< int > calculateShufflevectorMask(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:547
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:712
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:135
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:113
bool isReassocChainLink(const Instruction *I)
Definition SLPUtils.cpp:58
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:287
@ SecondArg
The mask is expected to be for permutation of 2 vectors, check for the mask elements for the second a...
Definition SLPUtils.h:291
@ UndefsAsMask
Consider undef mask elements (-1) as placeholders for future shuffle elements and mark them as ones a...
Definition SLPUtils.h:294
@ FirstArg
The mask is expected to be for permutation of 1-2 vectors, check for the mask elements for the first ...
Definition SLPUtils.h:288
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:865
bool isSimple(Instruction *I)
Definition SLPUtils.cpp:815
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:42
unsigned getShufflevectorNumGroups(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:507
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:587
SmallVector< Constant * > replicateMask(ArrayRef< Constant * > Val, unsigned VF)
Replicates the given Val VF times.
Definition SLPUtils.cpp:928
unsigned getReassocCombineOpcode(unsigned Opcode)
Definition SLPUtils.cpp:47
bool isVectorLikeInstWithConstOps(Value *V)
Checks if V is one of vector-like instructions, i.e.
Definition SLPUtils.cpp:66
bool doesNotNeedToBeScheduled(Value *V)
Checks if the specified value does not require scheduling.
Definition SLPUtils.cpp:483
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:98
constexpr int UsesLimit
Limit of the number of uses for potentially transformed instructions/values, used in checks to avoid ...
Definition SLPUtils.h:46
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:38
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...
Definition SLPUtils.cpp:956
Value * createExtractVector(IRBuilderBase &Builder, Value *Vec, unsigned SubVecVF, unsigned Index)
Generates subvector extract using Generator or using default shuffle.
Definition SLPUtils.cpp:705
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:890
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
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:1739
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:2554
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:1702
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
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:1746
ElementCount getVectorizedTypeVF(Type *Ty)
Returns the number of vector elements for a vectorized type.
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:1753
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
TargetTransformInfo TTI
DWARFExpression::Operation Op
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:1772
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
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