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"
20#include "llvm/IR/DebugInfo.h"
22#include "llvm/IR/IRBuilder.h"
29
30#include <algorithm>
31#include <numeric>
32#include <string>
33#include <type_traits>
34
35using namespace llvm;
36using namespace llvm::PatternMatch;
37
38namespace llvm::slpvectorizer {
39
43
44bool isBinOpIdentityConstant(const Value *V, unsigned Opcode) {
45 const auto *CI = dyn_cast<ConstantInt>(V);
46 return CI && ConstantExpr::getBinOpIdentity(Opcode, CI->getType()) == CI;
47}
48
49unsigned getReassocCombineOpcode(unsigned Opcode) {
50 switch (Opcode) {
51 case Instruction::Sub:
52 return Instruction::Add;
53 case Instruction::FSub:
54 return Instruction::FAdd;
55 default:
56 return Opcode;
57 }
58}
59
61 if (I->getOpcode() == Instruction::Sub)
62 return true;
63 if (I->getOpcode() == Instruction::FSub)
64 return I->hasAllowReassoc();
65 return I->isAssociative();
66}
67
69 auto *I = dyn_cast<Instruction>(V);
70 // Non-instructions are vector-like only if they are undef.
71 if (!I)
72 return isa<UndefValue>(V);
73 switch (I->getOpcode()) {
74 case Instruction::ExtractValue:
75 case Instruction::InsertValue:
76 return true;
77 case Instruction::ExtractElement:
78 return isa<FixedVectorType>(I->getOperand(0)->getType()) &&
79 isConstant(I->getOperand(1));
80 case Instruction::InsertElement:
81 return isa<FixedVectorType>(I->getOperand(0)->getType()) &&
82 isConstant(I->getOperand(2));
83 default:
84 return false;
85 }
86}
87
88unsigned getNumElements(Type *Ty) {
90 "ScalableVectorType is not supported.");
91 if (isVectorizedTy(Ty))
93 return 1;
94}
95
96unsigned getPartNumElems(unsigned Size, unsigned NumParts) {
97 return std::min<unsigned>(Size, bit_ceil(divideCeil(Size, NumParts)));
98}
99
100unsigned getNumElems(unsigned Size, unsigned PartNumElems, unsigned Part) {
101 return std::min<unsigned>(PartNumElems, Size - Part * PartNumElems);
102}
103
104#if !defined(NDEBUG)
105std::string shortBundleName(ArrayRef<Value *> VL, int Idx) {
106 std::string Result;
107 raw_string_ostream OS(Result);
108 if (Idx >= 0)
109 OS << "Idx: " << Idx << ", ";
110 OS << "n=" << VL.size() << " [" << *VL.front() << ", ..]";
111 return Result;
112}
113#endif
114
116 auto *It = find_if(VL, IsaPred<Instruction>);
117 if (It == VL.end())
118 return false;
121 return true;
122
123 BasicBlock *BB = I0->getParent();
124 for (Value *V : make_filter_range(iterator_range(It, VL.end()), [](Value *V) {
125 return !isa<PoisonValue>(V);
126 })) {
127 auto *II = dyn_cast<Instruction>(V);
128 if (!II)
129 return false;
130
131 if (BB != II->getParent())
132 return false;
133 }
134 return true;
135}
136
138 // Constant expressions and globals can't be vectorized like normal integer/FP
139 // constants.
140 return all_of(VL, isConstant);
141}
142
144 Value *FirstNonUndef = nullptr;
145 for (Value *V :
146 make_filter_range(VL, [](Value *V) { return !isa<UndefValue>(V); })) {
147 if (!FirstNonUndef) {
148 FirstNonUndef = V;
149 continue;
150 }
151 if (V != FirstNonUndef)
152 return false;
153 }
154 return FirstNonUndef != nullptr;
155}
156
158 if (LHS == RHS)
159 return RHS;
160 if ((LHS == Intrinsic::fma || LHS == Intrinsic::fmuladd) &&
161 (RHS == Intrinsic::fma || RHS == Intrinsic::fmuladd))
162 return Intrinsic::fma;
164}
165
166bool isCommutative(const Instruction *I, const Value *ValWithUses,
167 bool IsCopyable) {
168 if (auto *Cmp = dyn_cast<CmpInst>(I))
169 return Cmp->isCommutative();
170 if (auto *BO = dyn_cast<BinaryOperator>(I))
171 return BO->isCommutative() ||
172 (BO->getOpcode() == Instruction::Sub && ValWithUses->hasUseList() &&
173 !ValWithUses->hasNUsesOrMore(UsesLimit) &&
174 all_of(
175 ValWithUses->uses(),
176 [&](const Use &U) {
177 // Commutative, if icmp eq/ne sub, 0
178 CmpPredicate Pred;
179 if (match(U.getUser(),
180 m_ICmp(Pred, m_Specific(U.get()), m_Zero())) &&
181 (Pred == ICmpInst::ICMP_EQ || Pred == ICmpInst::ICMP_NE))
182 return true;
183 // Commutative, if abs(sub nsw, true) or abs(sub, false).
184 ConstantInt *Flag;
185 auto *I = dyn_cast<BinaryOperator>(U.get());
186 return match(U.getUser(),
187 m_Intrinsic<Intrinsic::abs>(
188 m_Specific(U.get()), m_ConstantInt(Flag))) &&
189 ((!IsCopyable && I && !I->hasNoSignedWrap()) ||
190 Flag->isOne());
191 })) ||
192 (BO->getOpcode() == Instruction::FSub && ValWithUses->hasUseList() &&
193 !ValWithUses->hasNUsesOrMore(UsesLimit) &&
194 all_of(ValWithUses->uses(), [](const Use &U) {
195 return match(U.getUser(),
196 m_Intrinsic<Intrinsic::fabs>(m_Specific(U.get())));
197 }));
198 return I->isCommutative();
199}
200
201bool isCommutative(const Instruction *I) { return isCommutative(I, I); }
202
203bool isCommutableOperand(const Instruction *I, Value *ValWithUses, unsigned Op,
204 bool IsCopyable) {
205 assert(isCommutative(I, ValWithUses, IsCopyable) &&
206 "The instruction is not commutative.");
207 if (isa<CmpInst>(I))
208 return true;
209 if (auto *BO = dyn_cast<BinaryOperator>(I)) {
210 switch (BO->getOpcode()) {
211 case Instruction::Sub:
212 case Instruction::FSub:
213 return true;
214 default:
215 break;
216 }
217 }
218 return I->isCommutableOperand(Op);
219}
220
223 // IntrinsicInst::isCommutative returns true if swapping the first "two"
224 // arguments to the intrinsic produces the same result.
225 constexpr unsigned IntrinsicNumOperands = 2;
226 return IntrinsicNumOperands;
227 }
228 return I->getNumOperands();
229}
230
231std::optional<unsigned> getElementIndex(const Value *Inst, unsigned Offset) {
232 if (auto Index = getInsertExtractIndex<InsertElementInst>(Inst, Offset))
233 return Index;
235 return Index;
236
237 unsigned Index = Offset;
238
239 const auto *IV = dyn_cast<InsertValueInst>(Inst);
240 if (!IV)
241 return std::nullopt;
242
243 Type *CurrentType = IV->getType();
244 for (unsigned I : IV->indices()) {
245 if (const auto *ST = dyn_cast<StructType>(CurrentType)) {
246 Index *= ST->getNumElements();
247 CurrentType = ST->getElementType(I);
248 } else if (const auto *AT = dyn_cast<ArrayType>(CurrentType)) {
249 Index *= AT->getNumElements();
250 CurrentType = AT->getElementType();
251 } else {
252 return std::nullopt;
253 }
254 Index += I;
255 }
256 return Index;
257}
258
260 auto *It = find_if(VL, IsaPred<Instruction>);
261 if (It == VL.end())
262 return true;
263 Instruction *MainOp = cast<Instruction>(*It);
264 unsigned Opcode = MainOp->getOpcode();
265 bool IsCmpOp = isa<CmpInst>(MainOp);
266 CmpInst::Predicate BasePred = IsCmpOp ? cast<CmpInst>(MainOp)->getPredicate()
268 return all_of(make_range(It, VL.end()), [&](Value *V) {
269 if (auto *CI = dyn_cast<CmpInst>(V))
270 return BasePred == CI->getPredicate();
271 if (auto *I = dyn_cast<Instruction>(V))
272 return I->getOpcode() == Opcode;
273 return isa<PoisonValue>(V);
274 });
275}
276
277std::optional<unsigned> getExtractIndex(const Instruction *E) {
278 unsigned Opcode = E->getOpcode();
279 assert((Opcode == Instruction::ExtractElement ||
280 Opcode == Instruction::ExtractValue) &&
281 "Expected extractelement or extractvalue instruction.");
282 if (Opcode == Instruction::ExtractElement) {
283 auto *CI = dyn_cast<ConstantInt>(E->getOperand(1));
284 if (!CI)
285 return std::nullopt;
286 // Check if the index is out of bound. We can get the source vector from
287 // operand 0.
288 unsigned Idx = CI->getZExtValue();
289 auto *EE = cast<ExtractElementInst>(E);
290 const unsigned VF = getNumElements(EE->getVectorOperandType());
291 if (Idx >= VF)
292 return std::nullopt;
293 return Idx;
294 }
295 auto *EI = cast<ExtractValueInst>(E);
296 if (EI->getNumIndices() != 1)
297 return std::nullopt;
298 return *EI->idx_begin();
299}
300
302 SmallVectorImpl<int> &Mask) {
303 Mask.clear();
304 const unsigned E = Indices.size();
305 Mask.resize(E, PoisonMaskElem);
306 for (unsigned I = 0; I < E; ++I)
307 Mask[Indices[I]] = I;
308}
309
311 assert(!Mask.empty() && "Expected non-empty mask.");
312 SmallVector<Value *> Prev(Scalars.size(),
313 PoisonValue::get(Scalars.front()->getType()));
314 Prev.swap(Scalars);
315 for (unsigned I = 0, E = Prev.size(); I < E; ++I)
316 if (Mask[I] != PoisonMaskElem)
317 Scalars[Mask[I]] = Prev[I];
318}
319
321 assert(!Mask.empty() && Reuses.size() == Mask.size() &&
322 "Expected non-empty mask.");
323 SmallVector<int> Prev(Reuses.begin(), Reuses.end());
324 Prev.swap(Reuses);
325 for (unsigned I = 0, E = Prev.size(); I < E; ++I)
326 if (Mask[I] != PoisonMaskElem)
327 Reuses[Mask[I]] = Prev[I];
328}
329
331 bool BottomOrder) {
332 assert(!Mask.empty() && "Expected non-empty mask.");
333 unsigned Sz = Mask.size();
334 if (BottomOrder) {
335 SmallVector<unsigned> PrevOrder;
336 if (Order.empty()) {
337 PrevOrder.resize(Sz);
338 std::iota(PrevOrder.begin(), PrevOrder.end(), 0);
339 } else {
340 PrevOrder.swap(Order);
341 }
342 Order.assign(Sz, Sz);
343 for (unsigned I = 0; I < Sz; ++I)
344 if (Mask[I] != PoisonMaskElem)
345 Order[I] = PrevOrder[Mask[I]];
346 if (all_of(enumerate(Order), [&](const auto &Data) {
347 return Data.value() == Sz || Data.index() == Data.value();
348 })) {
349 Order.clear();
350 return;
351 }
353 return;
354 }
355 SmallVector<int> MaskOrder;
356 if (Order.empty()) {
357 MaskOrder.resize(Sz);
358 std::iota(MaskOrder.begin(), MaskOrder.end(), 0);
359 } else {
360 inversePermutation(Order, MaskOrder);
361 }
362 reorderReuses(MaskOrder, Mask);
363 if (ShuffleVectorInst::isIdentityMask(MaskOrder, Sz)) {
364 Order.clear();
365 return;
366 }
367 Order.assign(Sz, Sz);
368 for (unsigned I = 0; I < Sz; ++I)
369 if (MaskOrder[I] != PoisonMaskElem)
370 Order[MaskOrder[I]] = I;
372}
373
375 assert(!Order.empty() &&
376 "Order is empty. Please check it before using isReverseOrder.");
377 unsigned Sz = Order.size();
378 return all_of(enumerate(Order), [&](const auto &Pair) {
379 return Pair.value() == Sz || Sz - Pair.index() - 1 == Pair.value();
380 });
381}
382
384 ArrayRef<int> FirstCluster = Mask.slice(0, Sz);
385 if (ShuffleVectorInst::isIdentityMask(FirstCluster, Sz))
386 return false;
387 for (unsigned I = Sz, E = Mask.size(); I < E; I += Sz) {
388 ArrayRef<int> Cluster = Mask.slice(I, Sz);
389 if (Cluster != FirstCluster)
390 return false;
391 }
392 return true;
393}
394
396 ArrayRef<unsigned> SecondaryOrder) {
397 assert((SecondaryOrder.empty() || Order.size() == SecondaryOrder.size()) &&
398 "Expected same size of orders");
399 size_t Sz = Order.size();
400 SmallBitVector UsedIndices(Sz);
401 for (unsigned Idx : seq<unsigned>(0, Sz)) {
402 if (Order[Idx] != Sz)
403 UsedIndices.set(Order[Idx]);
404 }
405 if (SecondaryOrder.empty()) {
406 for (unsigned Idx : seq<unsigned>(0, Sz))
407 if (Order[Idx] == Sz && !UsedIndices.test(Idx))
408 Order[Idx] = Idx;
409 } else {
410 for (unsigned Idx : seq<unsigned>(0, Sz))
411 if (SecondaryOrder[Idx] != Sz && Order[Idx] == Sz &&
412 !UsedIndices.test(SecondaryOrder[Idx]))
413 Order[Idx] = SecondaryOrder[Idx];
414 }
415}
416
418 assert(!VL.empty() && "Expected non-empty list of values.");
419 Type *Ty = VL.consume_front()->getType();
420 return all_of(VL, [&](Value *V) { return V->getType() == Ty; });
421}
422
423template <typename T>
424std::optional<unsigned> getInsertExtractIndex(const Value *Inst,
425 unsigned Offset) {
426 static_assert(std::is_same_v<T, InsertElementInst> ||
427 std::is_same_v<T, ExtractElementInst>,
428 "unsupported T");
429 const auto *IE = dyn_cast<T>(Inst);
430 if (!IE)
431 return std::nullopt;
432 // InsertElement: result is the vector, index is op 2.
433 // ExtractElement: result is scalar, vector is op 0, index is op 1.
434 constexpr bool IsInsert = std::is_same_v<T, InsertElementInst>;
435 Type *VecTy = IsInsert ? IE->getType() : IE->getOperand(0)->getType();
436 const auto *VT = dyn_cast<FixedVectorType>(VecTy);
437 if (!VT)
438 return std::nullopt;
439 const auto *CI = dyn_cast<ConstantInt>(IE->getOperand(IsInsert ? 2 : 1));
440 if (!CI)
441 return std::nullopt;
442 if (CI->getValue().uge(VT->getNumElements()))
443 return std::nullopt;
444 unsigned Index = Offset;
445 Index *= VT->getNumElements();
446 Index += CI->getZExtValue();
447 return Index;
448}
449
450// Only these two specializations are used; instantiate them here so the
451// definition can stay out of the header.
452template std::optional<unsigned>
454template std::optional<unsigned>
456
458 auto *I = dyn_cast<Instruction>(V);
459 if (!I)
460 return true;
461 return !mayHaveNonDefUseDependency(*I) &&
463 [I](Instruction *IO) {
464 return isa<PHINode>(IO) || IO->getParent() != I->getParent();
465 });
466}
467
469 auto *I = dyn_cast<Instruction>(V);
470 if (!I)
471 return true;
472 // Limits the number of uses to save compile time.
473 return !I->mayReadOrWriteMemory() && !I->hasNUsesOrMore(UsesLimit) &&
474 all_of(I->users(), [I](User *U) {
475 auto *IU = dyn_cast<Instruction>(U);
476 if (!IU)
477 return true;
478 return IU->getParent() != I->getParent() || isa<PHINode>(IU);
479 });
480}
481
485
490
491void transformScalarShuffleIndiciesToVector(unsigned VecTyNumElements,
492 SmallVectorImpl<int> &Mask) {
493 // The ShuffleBuilder implementation use shufflevector to splat an "element".
494 // But the element have different meaning for SLP (scalar) and REVEC
495 // (vector). We need to expand Mask into masks which shufflevector can use
496 // directly.
497 SmallVector<int> NewMask(Mask.size() * VecTyNumElements);
498 for (unsigned I : seq<unsigned>(Mask.size()))
499 for (auto [J, MaskV] : enumerate(MutableArrayRef(NewMask).slice(
500 I * VecTyNumElements, VecTyNumElements)))
501 MaskV = Mask[I] == PoisonMaskElem ? PoisonMaskElem
502 : Mask[I] * VecTyNumElements + J;
503 Mask.swap(NewMask);
504}
505
507 if (VL.empty())
508 return 0;
510 return 0;
511 auto *SV = cast<ShuffleVectorInst>(VL.front());
512 unsigned SVNumElements =
513 cast<FixedVectorType>(SV->getOperand(0)->getType())->getNumElements();
514 unsigned ShuffleMaskSize = SV->getShuffleMask().size();
515 if (SVNumElements % ShuffleMaskSize != 0)
516 return 0;
517 unsigned GroupSize = SVNumElements / ShuffleMaskSize;
518 if (GroupSize == 0 || (VL.size() % GroupSize) != 0)
519 return 0;
520 unsigned NumGroup = 0;
521 for (size_t I = 0, E = VL.size(); I != E; I += GroupSize) {
522 auto *SV = cast<ShuffleVectorInst>(VL[I]);
523 Value *Src = SV->getOperand(0);
524 ArrayRef<Value *> Group = VL.slice(I, GroupSize);
525 SmallBitVector ExpectedIndex(GroupSize);
526 if (!all_of(Group, [&](Value *V) {
527 auto *SV = cast<ShuffleVectorInst>(V);
528 // From the same source.
529 if (SV->getOperand(0) != Src)
530 return false;
531 int Index;
532 if (!SV->isExtractSubvectorMask(Index))
533 return false;
534 ExpectedIndex.set(Index / ShuffleMaskSize);
535 return true;
536 }))
537 return 0;
538 if (!ExpectedIndex.all())
539 return 0;
540 ++NumGroup;
541 }
542 assert(NumGroup == (VL.size() / GroupSize) && "Unexpected number of groups");
543 return NumGroup;
544}
545
547 assert(getShufflevectorNumGroups(VL) && "Not supported shufflevector usage.");
548 auto *SV = cast<ShuffleVectorInst>(VL.front());
549 unsigned SVNumElements =
550 cast<FixedVectorType>(SV->getOperand(0)->getType())->getNumElements();
551 SmallVector<int> Mask;
552 unsigned AccumulateLength = 0;
553 for (Value *V : VL) {
554 auto *SV = cast<ShuffleVectorInst>(V);
555 for (int M : SV->getShuffleMask())
556 Mask.push_back(M == PoisonMaskElem ? PoisonMaskElem
557 : AccumulateLength + M);
558 AccumulateLength += SVNumElements;
559 }
560 return Mask;
561}
562
563/// Checks if the vector of instructions can be represented as a shuffle, like:
564/// %x0 = extractelement <4 x i8> %x, i32 0
565/// %x3 = extractelement <4 x i8> %x, i32 3
566/// %y1 = extractelement <4 x i8> %y, i32 1
567/// %y2 = extractelement <4 x i8> %y, i32 2
568/// %x0x0 = mul i8 %x0, %x0
569/// %x3x3 = mul i8 %x3, %x3
570/// %y1y1 = mul i8 %y1, %y1
571/// %y2y2 = mul i8 %y2, %y2
572/// %ins1 = insertelement <4 x i8> poison, i8 %x0x0, i32 0
573/// %ins2 = insertelement <4 x i8> %ins1, i8 %x3x3, i32 1
574/// %ins3 = insertelement <4 x i8> %ins2, i8 %y1y1, i32 2
575/// %ins4 = insertelement <4 x i8> %ins3, i8 %y2y2, i32 3
576/// ret <4 x i8> %ins4
577/// can be transformed into:
578/// %1 = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 3, i32 5,
579/// i32 6>
580/// %2 = mul <4 x i8> %1, %1
581/// ret <4 x i8> %2
582/// Mask will return the Shuffle Mask equivalent to the extracted elements.
583/// TODO: Can we split off and reuse the shuffle mask detection from
584/// ShuffleVectorInst/getShuffleCost?
585std::optional<TargetTransformInfo::ShuffleKind>
587 AssumptionCache *AC) {
588 const auto *It = find_if(VL, IsaPred<ExtractElementInst>);
589 if (It == VL.end())
590 return std::nullopt;
591 unsigned Size = accumulate(VL, 0u, [](unsigned S, Value *V) {
592 auto *EI = dyn_cast<ExtractElementInst>(V);
593 if (!EI)
594 return S;
595 auto *VTy = dyn_cast<FixedVectorType>(EI->getVectorOperandType());
596 if (!VTy)
597 return S;
598 return std::max(S, VTy->getNumElements());
599 });
600
601 Value *Vec1 = nullptr;
602 Value *Vec2 = nullptr;
603 bool HasNonUndefVec = any_of(make_isa_range<ExtractElementInst>(VL),
604 [&](ExtractElementInst *EE) {
605 Value *Vec = EE->getVectorOperand();
606 if (isa<UndefValue>(Vec))
607 return false;
608 return isGuaranteedNotToBePoison(Vec, AC);
609 });
610 enum ShuffleMode { Unknown, Select, Permute };
611 ShuffleMode CommonShuffleMode = Unknown;
612 Mask.assign(VL.size(), PoisonMaskElem);
613 for (unsigned I = 0, E = VL.size(); I < E; ++I) {
614 // Undef, or a copyable lane modeled on an extract main op, can be
615 // represented as an undef element in a vector.
616 if (isa<UndefValue>(VL[I]))
617 continue;
618 auto *EI = dyn_cast<ExtractElementInst>(VL[I]);
619 if (!EI)
620 continue;
621 if (isa<ScalableVectorType>(EI->getVectorOperandType()))
622 return std::nullopt;
623 auto *Vec = EI->getVectorOperand();
624 // We can extractelement from undef or poison vector.
626 continue;
627 // All vector operands must have the same number of vector elements.
628 if (isa<UndefValue>(Vec)) {
629 Mask[I] = I;
630 } else {
631 if (isa<UndefValue>(EI->getIndexOperand()))
632 continue;
633 auto *Idx = dyn_cast<ConstantInt>(EI->getIndexOperand());
634 if (!Idx)
635 return std::nullopt;
636 // Undefined behavior if Idx is negative or >= Size.
637 if (Idx->getValue().uge(Size))
638 continue;
639 unsigned IntIdx = Idx->getValue().getZExtValue();
640 Mask[I] = IntIdx;
641 }
642 if (isUndefVector(Vec).all() && HasNonUndefVec)
643 continue;
644 // For correct shuffling we have to have at most 2 different vector operands
645 // in all extractelement instructions.
646 if (!Vec1 || Vec1 == Vec) {
647 Vec1 = Vec;
648 } else if (!Vec2 || Vec2 == Vec) {
649 Vec2 = Vec;
650 Mask[I] += Size;
651 } else {
652 return std::nullopt;
653 }
654 if (CommonShuffleMode == Permute)
655 continue;
656 // If the extract index is not the same as the operation number, it is a
657 // permutation.
658 if (Mask[I] % Size != I) {
659 CommonShuffleMode = Permute;
660 continue;
661 }
662 CommonShuffleMode = Select;
663 }
664 // If we're not crossing lanes in different vectors, consider it as blending.
665 if (CommonShuffleMode == Select && Vec2)
667 // If Vec2 was never used, we have a permutation of a single vector, otherwise
668 // we have permutation of 2 vectors.
671}
672
674 IRBuilderBase &Builder, Value *Vec, Value *V, unsigned Index,
675 function_ref<Value *(Value *, Value *, ArrayRef<int>)> Generator) {
676 if (isa<PoisonValue>(Vec) && isa<PoisonValue>(V))
677 return Vec;
678 const unsigned SubVecVF = getNumElements(V->getType());
679 // Create shuffle, insertvector requires that index is multiple of
680 // the subvector length.
681 const unsigned VecVF = getNumElements(Vec->getType());
682 SmallVector<int> Mask(VecVF, PoisonMaskElem);
683 if (isa<PoisonValue>(Vec)) {
684 auto *Begin = std::next(Mask.begin(), Index);
685 std::iota(Begin, std::next(Begin, SubVecVF), 0);
686 Vec = Builder.CreateShuffleVector(V, Mask);
687 return Vec;
688 }
689 std::iota(Mask.begin(), Mask.end(), 0);
690 std::iota(std::next(Mask.begin(), Index),
691 std::next(Mask.begin(), Index + SubVecVF), VecVF);
692 if (Generator)
693 return Generator(Vec, V, Mask);
694 // 1. Resize V to the size of Vec.
695 SmallVector<int> ResizeMask(VecVF, PoisonMaskElem);
696 std::iota(ResizeMask.begin(), std::next(ResizeMask.begin(), SubVecVF), 0);
697 V = Builder.CreateShuffleVector(V, ResizeMask);
698 // 2. Insert V into Vec.
699 return Builder.CreateShuffleVector(Vec, V, Mask);
700}
701
703 unsigned SubVecVF, unsigned Index) {
704 SmallVector<int> Mask(SubVecVF, PoisonMaskElem);
705 std::iota(Mask.begin(), Mask.end(), Index);
706 return Builder.CreateShuffleVector(Vec, Mask);
707}
708
710 SmallBitVector UseMask(VF, true);
711 for (auto [Idx, Value] : enumerate(Mask)) {
712 if (Value == PoisonMaskElem) {
713 if (MaskArg == UseMask::UndefsAsMask)
714 UseMask.reset(Idx);
715 continue;
716 }
717 if (MaskArg == UseMask::FirstArg && Value < VF)
718 UseMask.reset(Value);
719 else if (MaskArg == UseMask::SecondArg && Value >= VF)
720 UseMask.reset(Value - VF);
721 }
722 return UseMask;
723}
724
725template <bool IsPoisonOnly>
727 SmallBitVector Res(UseMask.empty() ? 1 : UseMask.size(), true);
728 using T = std::conditional_t<IsPoisonOnly, PoisonValue, UndefValue>;
729 if (isa<T>(V))
730 return Res;
731 auto *VecTy = dyn_cast<FixedVectorType>(V->getType());
732 if (!VecTy)
733 return Res.reset();
734 auto *C = dyn_cast<Constant>(V);
735 if (!C) {
736 if (!UseMask.empty()) {
737 const Value *Base = V;
738 while (auto *II = dyn_cast<InsertElementInst>(Base)) {
739 Base = II->getOperand(0);
740 if (isa<T>(II->getOperand(1)))
741 continue;
742 std::optional<unsigned> Idx = getElementIndex(II);
743 if (!Idx) {
744 Res.reset();
745 return Res;
746 }
747 if (*Idx < UseMask.size() && !UseMask.test(*Idx))
748 Res.reset(*Idx);
749 }
750 // TODO: Add analysis for shuffles here too.
751 if (V == Base) {
752 Res.reset();
753 } else {
754 SmallBitVector SubMask(UseMask.size(), false);
755 Res &= isUndefVector<IsPoisonOnly>(Base, SubMask);
756 }
757 } else {
758 Res.reset();
759 }
760 return Res;
761 }
762 for (unsigned I = 0, E = VecTy->getNumElements(); I != E; ++I) {
763 if (Constant *Elem = C->getAggregateElement(I))
764 if (!isa<T>(Elem) &&
765 (UseMask.empty() || (I < UseMask.size() && !UseMask.test(I))))
766 Res.reset(I);
767 }
768 return Res;
769}
770
772 const SmallBitVector &);
774 const SmallBitVector &);
775
778 const TargetTransformInfo *TTI) {
779 if (!UserInst)
780 return false;
781 unsigned Opcode = UserInst->getOpcode();
782 switch (Opcode) {
783 case Instruction::Load: {
784 LoadInst *LI = cast<LoadInst>(UserInst);
785 return (LI->getPointerOperand() == Scalar);
786 }
787 case Instruction::Store: {
788 StoreInst *SI = cast<StoreInst>(UserInst);
789 return (SI->getPointerOperand() == Scalar);
790 }
791 case Instruction::Call: {
792 CallInst *CI = cast<CallInst>(UserInst);
794 return any_of(enumerate(CI->args()), [&](auto &&Arg) {
795 return isVectorIntrinsicWithScalarOpAtArg(ID, Arg.index(), TTI) &&
796 Arg.value().get() == Scalar;
797 });
798 }
799 default:
800 return false;
801 }
802}
803
811
813 if (LoadInst *LI = dyn_cast<LoadInst>(I))
814 return LI->isSimple();
816 return SI->isSimple();
818 return !MI->isVolatile();
819 return true;
820}
821
822bool isSelectedBaseLoad(Type *ScalarTy, ArrayRef<Value *> PointerOps,
823 const DataLayout &DL, Value *&TrueBase,
824 Value *&FalseBase,
825 SmallVectorImpl<Value *> &Conditions) {
826 TrueBase = nullptr;
827 FalseBase = nullptr;
828 uint64_t ScalarSize = DL.getTypeStoreSize(ScalarTy);
829 Conditions.assign(PointerOps.size(), nullptr);
830 for (auto [Idx, P] : enumerate(PointerOps)) {
831 Value *Base = P;
832 uint64_t Offset = 0;
833 if (auto *GEP = dyn_cast<GetElementPtrInst>(P)) {
834 APInt OffsetAP(DL.getIndexTypeSizeInBits(GEP->getType()), 0);
835 if (!GEP->accumulateConstantOffset(DL, OffsetAP) || OffsetAP.isNegative())
836 return false;
837 Offset = OffsetAP.getZExtValue();
838 Base = GEP->getPointerOperand();
839 }
840 auto *Sel = dyn_cast<SelectInst>(Base);
841 if (!Sel)
842 return false;
843 Value *T = Sel->getTrueValue();
844 Value *F = Sel->getFalseValue();
845 if (!TrueBase) {
846 if (T == F)
847 return false;
848 TrueBase = T;
849 FalseBase = F;
850 } else if (TrueBase != T || FalseBase != F) {
851 return false;
852 }
853 // Lane Idx must be at exactly Base + Idx * sizeof(ScalarTy); codegen reads
854 // contiguously from TrueBase/FalseBase starting at lane 0.
855 if (Offset != static_cast<uint64_t>(Idx) * ScalarSize)
856 return false;
857 Conditions[Idx] = Sel->getCondition();
858 }
859 return TrueBase != nullptr;
860}
861
863 function_ref<bool(Value *)> IsGEPLane,
864 const DataLayout &DL) {
865 constexpr unsigned IndexIdx = 1;
866 Type *VL0Ty = VL0->getOperand(IndexIdx)->getType();
867 Type *PtrIdxTy =
868 DL.getIndexType(VL0->getOperand(0)->getType()->getScalarType());
869 bool AllSameTy = true;
870 bool HasNonConstIdx = false;
871 bool ConstsFitVL0Ty = true;
872 for (Value *V : make_filter_range(VL, IsGEPLane)) {
873 Value *Op = cast<GetElementPtrInst>(V)->getOperand(IndexIdx);
874 if (Op->getType() != VL0Ty)
875 AllSameTy = false;
876 auto *CI = dyn_cast<ConstantInt>(Op);
877 if (!CI) {
878 // Non-constant indices are not cast, they must have the main op type.
879 if (Op->getType() != VL0Ty)
880 return nullptr;
881 HasNonConstIdx = true;
882 continue;
883 }
884 if (!CI->getValue().isSignedIntN(VL0Ty->getIntegerBitWidth()))
885 ConstsFitVL0Ty = false;
886 }
887 if (AllSameTy)
888 return VL0Ty;
889 if (!HasNonConstIdx || VL0Ty == PtrIdxTy)
890 return PtrIdxTy;
891 return ConstsFitVL0Ty ? VL0Ty : nullptr;
892}
893
895 SmallPtrSet<Value *, 16> UniquePtrs(llvm::from_range, PointerOps);
896 if (UniquePtrs.size() != PointerOps.size())
897 return false;
898 auto IsConstantOffsetPtr = [](Value *P) {
900 return !GEP ||
901 (GEP->getNumOperands() == 2 && isConstant(GEP->getOperand(1)));
902 };
903 auto *RefIt = find_if_not(PointerOps, IsConstantOffsetPtr);
904 if (RefIt == PointerOps.end())
905 return false;
906 auto *RefGEP = dyn_cast<GetElementPtrInst>(*RefIt);
907 if (!RefGEP || RefGEP->getNumOperands() != 2)
908 return false;
909 Value *Base = RefGEP->getPointerOperand();
910 Type *PtrTy = RefGEP->getType();
911 Type *SrcElemTy = RefGEP->getSourceElementType();
912 // The stride and the (optional) cast opcode of the runtime indices.
913 Value *Stride = nullptr;
914 unsigned CastOpcode = 0;
915 for (Value *P : PointerOps) {
916 if (P->getType() != PtrTy)
917 return false;
918 if (P == Base)
919 continue;
921 if (!GEP || GEP->getNumOperands() != 2 ||
922 GEP->getPointerOperand() != Base ||
923 GEP->getSourceElementType() != SrcElemTy)
924 return false;
925 Value *Idx = GEP->getOperand(1);
926 if (isConstant(Idx))
927 continue;
928 unsigned LaneCastOpcode = 0;
929 if (auto *Cast = dyn_cast<CastInst>(Idx)) {
930 LaneCastOpcode = Cast->getOpcode();
931 Idx = Cast->getOperand(0);
932 }
933 Value *LaneStride = Idx;
934 if (auto *BO = dyn_cast<BinaryOperator>(Idx)) {
935 if (isa<Constant>(BO->getOperand(1)))
936 LaneStride = BO->getOperand(0);
937 else if (isa<Constant>(BO->getOperand(0)))
938 LaneStride = BO->getOperand(1);
939 }
940 if (!Stride) {
941 Stride = LaneStride;
942 CastOpcode = LaneCastOpcode;
943 continue;
944 }
945 if (LaneStride != Stride || LaneCastOpcode != CastOpcode)
946 return false;
947 }
948 return Stride != nullptr;
949}
950
952 bool ExtendingManyInputs) {
953 if (SubMask.empty())
954 return;
955 assert(
956 (!ExtendingManyInputs || SubMask.size() > Mask.size() ||
957 // Check if input scalars were extended to match the size of other node.
958 (SubMask.size() == Mask.size() && Mask.back() == PoisonMaskElem)) &&
959 "SubMask with many inputs support must be larger than the mask.");
960 if (Mask.empty()) {
961 Mask.append(SubMask.begin(), SubMask.end());
962 return;
963 }
964 SmallVector<int> NewMask(SubMask.size(), PoisonMaskElem);
965 int TermValue = std::min(Mask.size(), SubMask.size());
966 for (int I = 0, E = SubMask.size(); I < E; ++I) {
967 if (SubMask[I] == PoisonMaskElem ||
968 (!ExtendingManyInputs &&
969 (SubMask[I] >= TermValue || Mask[SubMask[I]] >= TermValue)))
970 continue;
971 NewMask[I] = Mask[SubMask[I]];
972 }
973 Mask.swap(NewMask);
974}
975
977 const size_t Sz = Order.size();
978 SmallBitVector UnusedIndices(Sz, /*t=*/true);
979 SmallBitVector MaskedIndices(Sz);
980 for (unsigned I = 0; I < Sz; ++I) {
981 if (Order[I] < Sz)
982 UnusedIndices.reset(Order[I]);
983 else
984 MaskedIndices.set(I);
985 }
986 if (MaskedIndices.none())
987 return;
988 assert(UnusedIndices.count() == MaskedIndices.count() &&
989 "Non-synced masked/available indices.");
990 int Idx = UnusedIndices.find_first();
991 int MIdx = MaskedIndices.find_first();
992 while (MIdx >= 0) {
993 assert(Idx >= 0 && "Indices must be synced.");
994 Order[MIdx] = Idx;
995 Idx = UnusedIndices.find_next(Idx);
996 MIdx = MaskedIndices.find_next(MIdx);
997 }
998}
999
1001 unsigned Opcode0, unsigned Opcode1) {
1002 unsigned ScalarTyNumElements = getNumElements(ScalarTy);
1003 SmallBitVector OpcodeMask(VL.size() * ScalarTyNumElements, false);
1004 for (unsigned Lane : seq<unsigned>(VL.size())) {
1005 if (isa<PoisonValue>(VL[Lane]))
1006 continue;
1007 if (cast<Instruction>(VL[Lane])->getOpcode() == Opcode1)
1008 OpcodeMask.set(Lane * ScalarTyNumElements,
1009 Lane * ScalarTyNumElements + ScalarTyNumElements);
1010 }
1011 return OpcodeMask;
1012}
1013
1015 assert(none_of(Val, [](Constant *C) { return C->getType()->isVectorTy(); }) &&
1016 "Expected scalar constants.");
1017 SmallVector<Constant *> NewVal(Val.size() * VF);
1018 for (auto [I, V] : enumerate(Val))
1019 std::fill_n(NewVal.begin() + I * VF, VF, V);
1020 return NewVal;
1021}
1022
1024 switch (Opcode) {
1025 case Instruction::UDiv:
1026 return Intrinsic::masked_udiv;
1027 case Instruction::SDiv:
1028 return Intrinsic::masked_sdiv;
1029 case Instruction::URem:
1030 return Intrinsic::masked_urem;
1031 case Instruction::SRem:
1032 return Intrinsic::masked_srem;
1033 default:
1034 llvm_unreachable("Unexpected opcode");
1035 }
1036}
1037
1038/// Returns true if \p I is a part of a single-use chain, computing an address,
1039/// which does not pay off the vectorization: a constant table is accessed by a
1040/// gather, while the indices, unrelated between the lanes, require a full
1041/// buildvector, unlike the ones, shifted by a constant from a common base.
1043 constexpr unsigned MaxIndexChainLength = 3;
1044 // A constant shift of a common base is a cheap buildvector, while the loads
1045 // are vectorized together with the indices, computed from them.
1046 auto IsProfitableOperand = [](const Value *V) {
1047 if (isa<Constant>(V))
1048 return true;
1049 if (const auto *Cast = dyn_cast<CastInst>(V); Cast && Cast->hasOneUse())
1050 V = Cast->getOperand(0);
1051 return isa<LoadInst>(V);
1052 };
1053 const User *U = I->user_back();
1054 for ([[maybe_unused]] unsigned _ : seq<unsigned>(MaxIndexChainLength)) {
1055 if (const auto *GEP = dyn_cast<GetElementPtrInst>(U))
1056 return isa<Constant>(GEP->getPointerOperand()) ||
1057 none_of(I->operand_values(), IsProfitableOperand);
1058 if (!isa<Instruction>(U) || !U->hasOneUse())
1059 return false;
1060 U = U->user_back();
1061 }
1062 return false;
1063}
1064
1066 if (!I->hasOneUse() || isNonProfitableIndex(I))
1067 return false;
1068 // The operation with the identity or the absorbing constant is folded away
1069 // before the codegen, the vector node only repacks the lanes.
1070 if (const auto *BO = dyn_cast<BinaryOperator>(I)) {
1071 unsigned Opcode = BO->getOpcode();
1072 Type *Ty = BO->getType();
1073 for (unsigned Idx : seq<unsigned>(2)) {
1074 const auto *C = dyn_cast<Constant>(BO->getOperand(Idx));
1076 Opcode, Ty, /*AllowRHSConstant=*/Idx == 1) ||
1078 Opcode, Ty, /*AllowLHSConstant=*/Idx == 0)))
1079 return false;
1080 }
1081 }
1082 const User *U = I->user_back();
1085 if (isa<CastInst>(I))
1086 return !isa<FPToSIInst, FPToUIInst>(I) &&
1087 (!isa<CastInst>(U) || U->hasOneUse());
1089 I);
1090}
1091
1092Instruction *lookThroughCastRoundTrip(Value *V, bool MustBeElidable) {
1093 auto *Wide = dyn_cast<FPExtInst>(V);
1094 if (!Wide || !Wide->hasOneUse())
1095 return nullptr;
1096 auto *Narrow = dyn_cast<FPTruncInst>(Wide->getOperand(0));
1097 if (!Narrow || !Narrow->hasOneUse())
1098 return nullptr;
1099 Value *Src = Narrow->getOperand(0);
1100 if (!isa<Instruction>(Src) || Src->getType() != Wide->getType())
1101 return nullptr;
1102 if (MustBeElidable && !(Wide->hasAllowContract() && Wide->hasNoNaNs() &&
1103 Wide->hasNoInfs() && Narrow->hasAllowContract()))
1104 return nullptr;
1105 return Narrow;
1106}
1107
1108namespace {
1109
1110/// Shifts and the mask accumulated from the narrow ops on the current path:
1111/// the shifts above and at the narrow level, the bitwidth of the narrow ops
1112/// (0 if none) and the mask from the absorbed narrow ands.
1113struct NarrowedChainState {
1114 unsigned Shift = 0;
1115 unsigned NarrowShift = 0;
1116 unsigned NarrowBW = 0;
1117 APInt NarrowMask = APInt(1, 0);
1118
1119 /// The mask for the absorbed narrow ops in the leaf type, applied before
1120 /// widening and shifting; all-ones if nothing was absorbed.
1121 APInt getMask(unsigned LeafBW) const {
1122 if (NarrowBW == 0)
1123 return APInt::getAllOnes(LeafBW);
1124 return (NarrowMask & (APInt::getAllOnes(NarrowBW) << NarrowShift))
1125 .lshr(NarrowShift)
1126 .trunc(LeafBW);
1127 }
1128};
1129
1130} // namespace
1131
1132static void
1133collectNarrowedLeavesImpl(Value *V, unsigned RdxOpcode, unsigned WideBW,
1134 NarrowedChainState S, unsigned Depth,
1135 unsigned MaxDepth,
1137 SmallVectorImpl<Instruction *> &ChainInsts) {
1138 if (Depth < MaxDepth) {
1139 if (auto *Z = dyn_cast<ZExtInst>(V);
1140 Z && Z->getSrcTy()->isIntegerTy() && !Z->getSrcTy()->isIntegerTy(1)) {
1141 ChainInsts.push_back(Z);
1142 return collectNarrowedLeavesImpl(Z->getOperand(0), RdxOpcode, WideBW, S,
1143 Depth + 1, MaxDepth, Leaves, ChainInsts);
1144 }
1145 if (auto *BO = dyn_cast<BinaryOperator>(V)) {
1146 if (BO->getOpcode() == RdxOpcode) {
1147 ChainInsts.push_back(BO);
1148 collectNarrowedLeavesImpl(BO->getOperand(0), RdxOpcode, WideBW, S,
1149 Depth + 1, MaxDepth, Leaves, ChainInsts);
1150 collectNarrowedLeavesImpl(BO->getOperand(1), RdxOpcode, WideBW, S,
1151 Depth + 1, MaxDepth, Leaves, ChainInsts);
1152 return;
1153 }
1154 const APInt *Amt;
1155 unsigned BW = V->getType()->getScalarSizeInBits();
1156 auto *Z = dyn_cast<ZExtInst>(BO->getOperand(0));
1157 if (BO->getOpcode() == Instruction::Shl && Z && S.NarrowBW == 0 &&
1158 match(BO->getOperand(1), m_APInt(Amt)) && Amt->ult(BW) &&
1159 Z->getSrcTy()->isIntegerTy() && !Z->getSrcTy()->isIntegerTy(1) &&
1160 (BW == WideBW ||
1161 Z->getSrcTy()->getIntegerBitWidth() + Amt->getZExtValue() <= BW) &&
1162 S.Shift + Amt->getZExtValue() < WideBW) {
1163 ChainInsts.push_back(BO);
1164 ChainInsts.push_back(Z);
1165 S.Shift += Amt->getZExtValue();
1166 return collectNarrowedLeavesImpl(Z->getOperand(0), RdxOpcode, WideBW, S,
1167 Depth + 1, MaxDepth, Leaves,
1168 ChainInsts);
1169 }
1170 // Narrow shls fold into the shift and narrow ands into the mask; the
1171 // mask clears the bits the shls shift out. Only same-width ops compose
1172 // on one path, and the combined shift must stay a valid shift amount in
1173 // both types.
1174 if (BW < WideBW && (S.NarrowBW == 0 || BW == S.NarrowBW)) {
1175 if (BO->getOpcode() == Instruction::Shl &&
1176 match(BO->getOperand(1), m_APInt(Amt)) && Amt->ult(BW) &&
1177 S.NarrowShift + Amt->getZExtValue() < BW &&
1178 S.Shift + S.NarrowShift + Amt->getZExtValue() < WideBW) {
1179 ChainInsts.push_back(BO);
1180 if (BO->hasNoUnsignedWrap() && S.NarrowBW == 0) {
1181 S.Shift += Amt->getZExtValue();
1182 // Lossless shls shift out only known-zero bits; record them as
1183 // the mask so matching lanes can form a splat.
1184 S.NarrowBW = BW;
1185 S.NarrowMask = APInt::getLowBitsSet(BW, BW - Amt->getZExtValue());
1186 } else {
1187 if (S.NarrowBW == 0) {
1188 S.NarrowBW = BW;
1189 S.NarrowMask = APInt::getAllOnes(BW);
1190 }
1191 S.NarrowShift += Amt->getZExtValue();
1192 }
1193 return collectNarrowedLeavesImpl(BO->getOperand(0), RdxOpcode, WideBW,
1194 S, Depth + 1, MaxDepth, Leaves,
1195 ChainInsts);
1196 }
1197 Value *X;
1198 if (match(BO, m_c_And(m_Value(X), m_APInt(Amt)))) {
1199 ChainInsts.push_back(BO);
1200 if (S.NarrowBW == 0) {
1201 S.NarrowBW = BW;
1202 S.NarrowMask = APInt::getAllOnes(BW);
1203 }
1204 S.NarrowMask &= *Amt << S.NarrowShift;
1205 return collectNarrowedLeavesImpl(X, RdxOpcode, WideBW, S, Depth + 1,
1206 MaxDepth, Leaves, ChainInsts);
1207 }
1208 }
1209 }
1210 }
1211 Leaves.emplace_back(V, S.Shift + S.NarrowShift,
1212 S.getMask(V->getType()->getScalarSizeInBits()));
1213}
1214
1215void collectNarrowedLeaves(Value *V, unsigned RdxOpcode, unsigned WideBW,
1216 unsigned MaxDepth,
1218 SmallVectorImpl<Instruction *> &ChainInsts) {
1219 collectNarrowedLeavesImpl(V, RdxOpcode, WideBW, NarrowedChainState(),
1220 /*Depth=*/0, MaxDepth, Leaves, ChainInsts);
1221}
1222
1224 assert(F && "Expected function.");
1225 return F->hasOptSize() ? TTI::TCK_CodeSize : TTI::TCK_RecipThroughput;
1226}
1227
1228/// Checks if \p V is a zero-extended sub-field of a wider integer scalar.
1229/// Returns the source scalar, the field width and the field offset.
1230static std::optional<std::tuple<Value *, unsigned, unsigned>>
1232 if (!V->getType()->isIntegerTy())
1233 return std::nullopt;
1234 // Field offset for the field-aligned shift amount, if the shifted value of
1235 // the given bit width keeps at least one full field.
1236 auto GetFieldOffset = [](const APInt *Amt, unsigned BitWidth,
1237 unsigned FieldWidth) -> std::optional<unsigned> {
1238 uint64_t ShAmt = Amt->getLimitedValue(BitWidth);
1239 if (ShAmt % FieldWidth != 0 || ShAmt + FieldWidth > BitWidth)
1240 return std::nullopt;
1241 return ShAmt / FieldWidth;
1242 };
1243 // Checks if the low bits of Val are a sub-field of the given width of a
1244 // wider integer scalar. Val is a scalar integer, since V is one, and so is
1245 // the matched source.
1246 auto MatchLowField =
1247 [&](Value *Val,
1248 unsigned FieldWidth) -> std::optional<std::pair<Value *, unsigned>> {
1249 Value *Src;
1250 const APInt *Amt;
1251 // Only the low bits of Val are observed, so lshr and ashr are equivalent.
1252 if (match(Val, m_Trunc(m_Shr(m_Value(Src), m_APInt(Amt)))) ||
1253 match(Val, m_Shr(m_Value(Src), m_APInt(Amt)))) {
1254 if (std::optional<unsigned> Offset = GetFieldOffset(
1255 Amt, Src->getType()->getIntegerBitWidth(), FieldWidth)) {
1256 // The truncation of the shifted value keeps the field, look through it.
1257 match(Src, m_Trunc(m_Value(Src)));
1258 return std::make_pair(Src, *Offset);
1259 }
1260 return std::nullopt;
1261 }
1262 if (match(Val, m_Trunc(m_Value(Src))) &&
1263 Src->getType()->getIntegerBitWidth() >= FieldWidth)
1264 return std::make_pair(Src, 0u);
1265 // Val itself is the source of its low field.
1266 if (Val->getType()->getIntegerBitWidth() > FieldWidth)
1267 return std::make_pair(Val, 0u);
1268 return std::nullopt;
1269 };
1270 Value *Val;
1271 const APInt *Mask;
1272 // and Val, (1 << FieldWidth) - 1 or zext i<FieldWidth> Val - the low bits of
1273 // Val.
1274 unsigned FieldWidth = 0;
1275 if (match(V, m_c_And(m_Value(Val), m_APInt(Mask))) && Mask->isMask())
1276 FieldWidth = Mask->popcount();
1277 else if (match(V, m_ZExt(m_Value(Val))))
1278 FieldWidth = Val->getType()->getIntegerBitWidth();
1279 if (FieldWidth != 0) {
1280 if (std::optional<std::pair<Value *, unsigned>> Field =
1281 MatchLowField(Val, FieldWidth))
1282 return std::make_tuple(Field->first, FieldWidth, Field->second);
1283 return std::nullopt;
1284 }
1285 unsigned LaneWidth = V->getType()->getIntegerBitWidth();
1286 Value *Src;
1287 const APInt *Amt;
1288 if (match(V, m_Trunc(m_LShr(m_Value(Src), m_APInt(Amt))))) {
1289 unsigned SrcWidth = Src->getType()->getIntegerBitWidth();
1290 uint64_t ShAmt = Amt->getLimitedValue(SrcWidth);
1291 // The field itself, if the lane width is the field width.
1292 if (std::optional<unsigned> Offset =
1293 GetFieldOffset(Amt, SrcWidth, LaneWidth))
1294 return std::make_tuple(Src, LaneWidth, *Offset);
1295 // The zero-extended top field of the source.
1296 unsigned FieldWidth = SrcWidth - ShAmt;
1297 if (FieldWidth > 0 && FieldWidth < LaneWidth && ShAmt % FieldWidth == 0)
1298 return std::make_tuple(Src, FieldWidth, ShAmt / FieldWidth);
1299 return std::nullopt;
1300 }
1301 if (match(V, m_LShr(m_Value(Src), m_APInt(Amt)))) {
1302 // The zero-extended top field of the source, if the result keeps exactly
1303 // one field. Look through a truncation of the shifted value.
1304 unsigned ShfWidth = Src->getType()->getIntegerBitWidth();
1305 uint64_t ShAmt = Amt->getLimitedValue(ShfWidth);
1306 unsigned FieldWidth = ShfWidth - ShAmt;
1307 if (FieldWidth > 0 && ShAmt % FieldWidth == 0) {
1308 match(Src, m_Trunc(m_Value(Src)));
1309 return std::make_tuple(Src, FieldWidth, ShAmt / FieldWidth);
1310 }
1311 return std::nullopt;
1312 }
1313 if (match(V, m_Trunc(m_Value(Src))))
1314 return std::make_tuple(Src, LaneWidth, 0u);
1315 return std::nullopt;
1316}
1317
1318std::optional<std::tuple<Value *, unsigned, SmallVector<int>>>
1320 // Splats are emitted as broadcasts, sub-fields of a constant are folded.
1321 // The bitcast to the field vector maps lane 0 to the least significant
1322 // field on little-endian targets only.
1323 if (VL.size() < 2 || !VL.front()->getType()->isIntegerTy() || isSplat(VL) ||
1324 DL.isBigEndian())
1325 return std::nullopt;
1326 Value *Src = nullptr;
1327 unsigned FieldWidth = 0;
1329 for (auto [Idx, V] : make_filter_range(enumerate(VL), [](const auto &P) {
1330 return !isa<UndefValue>(P.value());
1331 })) {
1332 if (V->getType() != VL.front()->getType())
1333 return std::nullopt;
1334 std::optional<std::tuple<Value *, unsigned, unsigned>> Field =
1336 if (!Field || (Src && (Src != std::get<0>(*Field) ||
1337 FieldWidth != std::get<1>(*Field))))
1338 return std::nullopt;
1339 Src = std::get<0>(*Field);
1340 FieldWidth = std::get<1>(*Field);
1341 Mask[Idx] = std::get<2>(*Field);
1342 }
1343 // The field width is a whole number of bytes and divides the source
1344 // exactly, same as for the packing layout, so the source bitcasts to the
1345 // field vector.
1346 if (!Src || isa<Constant>(Src) || FieldWidth % 8 != 0 ||
1347 Src->getType()->getIntegerBitWidth() % FieldWidth != 0)
1348 return std::nullopt;
1349 // The same field in every lane is a splat, emitted as a broadcast.
1350 if (all_of(Mask, [First = *find_if(Mask, not_equal_to(PoisonMaskElem))](
1351 int MaskElt) {
1352 return MaskElt == PoisonMaskElem || MaskElt == First;
1353 }))
1354 return std::nullopt;
1355 return std::make_tuple(Src, FieldWidth, std::move(Mask));
1356}
1357
1358/// Deeper than the standard analysis recursion depth to keep the numeric
1359/// bound precise through arithmetic carry chains.
1361
1362APInt getScalarMaxValue(const Value *V, unsigned Depth) {
1363 unsigned BitWidth = V->getType()->getScalarSizeInBits();
1365 if (Depth > MaxBitPackAnalysisDepth || !V->getType()->isIntegerTy())
1366 return Unknown;
1367 const APInt *C, *Amt;
1368 if (match(V, m_APInt(C)))
1369 return *C;
1370 Value *L, *R;
1371 if (match(V, m_Add(m_Value(L), m_Value(R))) ||
1372 match(V, m_Or(m_Value(L), m_Value(R))) ||
1373 match(V, m_Xor(m_Value(L), m_Value(R))))
1374 return getScalarMaxValue(L, Depth + 1)
1376 if (match(V, m_NUWSub(m_Value(L), m_Value(R))))
1377 return getScalarMaxValue(L, Depth + 1);
1378 if (match(V, m_Mul(m_Value(L), m_Value(R))))
1379 return getScalarMaxValue(L, Depth + 1)
1381 if (match(V, m_And(m_Value(L), m_Value(R))))
1382 return APIntOps::umin(getScalarMaxValue(L, Depth + 1),
1383 getScalarMaxValue(R, Depth + 1));
1384 if (match(V, m_LShr(m_Value(L), m_APInt(Amt))) && Amt->ult(BitWidth))
1385 return getScalarMaxValue(L, Depth + 1).lshr(*Amt);
1386 if (match(V, m_Shl(m_Value(L), m_APInt(Amt))) && Amt->ult(BitWidth)) {
1387 APInt LMax = getScalarMaxValue(L, Depth + 1);
1388 return LMax.getActiveBits() + Amt->getZExtValue() <= BitWidth
1389 ? LMax.shl(*Amt)
1390 : Unknown;
1391 }
1392 if (match(V, m_ZExt(m_Value(L))))
1393 return getScalarMaxValue(L, Depth + 1).zext(BitWidth);
1394 if (match(V, m_Trunc(m_Value(L)))) {
1395 APInt Max = getScalarMaxValue(L, Depth + 1);
1396 return Max.getActiveBits() <= BitWidth ? Max.trunc(BitWidth) : Unknown;
1397 }
1398 if (match(V, m_SExt(m_Value(L)))) {
1399 APInt Max = getScalarMaxValue(L, Depth + 1);
1400 return Max.isNonNegative() ? Max.zext(BitWidth) : Unknown;
1401 }
1402 Value *F;
1403 if (match(V, m_Select(m_Value(), m_Value(L), m_Value(F))))
1404 return APIntOps::umax(getScalarMaxValue(L, Depth + 1),
1405 getScalarMaxValue(F, Depth + 1));
1406 return Unknown;
1407}
1408
1409std::optional<BitPackInfo> computeBitPackInfo(unsigned BitWidth,
1410 ArrayRef<APInt> PossibleBits,
1411 ArrayRef<uint64_t> ShlAmts,
1412 ArrayRef<APInt> Masks) {
1413 unsigned NumElts = PossibleBits.size();
1414 BitPackInfo Info;
1415 Info.LShrAmts.assign(NumElts, 0);
1416 for (unsigned Idx : seq(NumElts)) {
1417 APInt Possible = PossibleBits[Idx].shl(ShlAmts[Idx]) & Masks[Idx];
1418 if (Possible.isZero())
1419 continue;
1420 unsigned Lo, W;
1421 if (!Possible.isShiftedMask(Lo, W))
1422 return std::nullopt;
1423 if (Info.FieldWidth == 0) {
1424 if (W % 8 != 0 || BitWidth % W != 0)
1425 return std::nullopt;
1426 Info.FieldWidth = W;
1427 Info.LaneOfField.assign(BitWidth / W, BitPackInfo::NoLane);
1428 }
1429 if (W != Info.FieldWidth || Lo % W != 0)
1430 return std::nullopt;
1431 unsigned Field = Lo / W;
1432 if (Info.LaneOfField[Field] != BitPackInfo::NoLane)
1433 return std::nullopt;
1434 Info.LaneOfField[Field] = Idx;
1435 Info.LShrAmts[Idx] = Lo - ShlAmts[Idx];
1436 }
1437 if (Info.FieldWidth == 0)
1438 return std::nullopt;
1439 return Info;
1440}
1441
1442SmallVector<int> getBitPackMask(const BitPackInfo &Info, unsigned NumBytes,
1443 unsigned NumElts, unsigned BytesPerLane) {
1444 unsigned BytesPerField = Info.FieldWidth / 8;
1445 SmallVector<int> Mask;
1446 for (unsigned J : seq(NumBytes)) {
1447 unsigned Lane = Info.LaneOfField[J / BytesPerField];
1448 Mask.push_back(Lane == BitPackInfo::NoLane
1449 ? (int)(NumElts * BytesPerLane)
1450 : (int)(Lane * BytesPerLane + J % BytesPerField));
1451 }
1452 return Mask;
1453}
1454
1456 unsigned ShiftWidth, unsigned &NumInsts) {
1457 NumInsts = 0;
1458 auto *VecTy = cast<FixedVectorType>(X->getType());
1459 unsigned BitWidth = VecTy->getScalarSizeInBits();
1460 assert(BitWidth % 8 == 0 &&
1461 "The byte-multiple field width divides the result bit width.");
1462 unsigned NumElts = VecTy->getNumElements();
1463 Value *Y = X;
1464 if (ShiftWidth != BitWidth) {
1465 // Compacting a zext back to its source is free, use it directly.
1466 if (auto *Z = dyn_cast<ZExtInst>(X);
1467 Z && Z->getSrcTy()->getScalarSizeInBits() == ShiftWidth)
1468 Y = Z->getOperand(0);
1469 else {
1470 Y = Builder.CreateTrunc(
1471 Y, FixedVectorType::get(IntegerType::get(X->getContext(), ShiftWidth),
1472 NumElts));
1473 ++NumInsts;
1474 }
1475 }
1476 if (Info.needsShift()) {
1478 for (uint64_t A : Info.LShrAmts)
1479 Amts.push_back(
1480 ConstantInt::get(IntegerType::get(X->getContext(), ShiftWidth), A));
1481 Y = Builder.CreateLShr(Y, ConstantVector::get(Amts));
1482 ++NumInsts;
1483 }
1484 unsigned InBytes = NumElts * (ShiftWidth / 8);
1485 auto *ByteTy = FixedVectorType::get(Builder.getInt8Ty(), InBytes);
1486 SmallVector<int> Mask =
1487 getBitPackMask(Info, BitWidth / 8, NumElts, ShiftWidth / 8);
1488 auto *IntTy = IntegerType::get(X->getContext(), BitWidth);
1489 // A plain byte reversal of the shifted lanes is a bswap.
1490 if (ShuffleVectorInst::isReverseMask(Mask, InBytes)) {
1491 NumInsts += 2;
1492 return Builder.CreateUnaryIntrinsic(Intrinsic::bswap,
1493 Builder.CreateBitCast(Y, IntTy));
1494 }
1495 // An identity byte order needs no shuffle.
1496 if (ShuffleVectorInst::isIdentityMask(Mask, InBytes)) {
1497 ++NumInsts;
1498 return Builder.CreateBitCast(Y, IntTy);
1499 }
1500 Value *Packed = Builder.CreateShuffleVector(
1501 Builder.CreateBitCast(Y, ByteTy),
1502 is_contained(Info.LaneOfField, BitPackInfo::NoLane)
1503 ? Constant::getNullValue(ByteTy)
1504 : PoisonValue::get(ByteTy),
1505 Mask);
1506 NumInsts += 3;
1507 return Builder.CreateBitCast(Packed, IntTy);
1508}
1509
1512 findDbgValues(&From, DVRs);
1513 auto *ExI = dyn_cast<Instruction>(&To);
1514 for (DbgVariableRecord *DVR : DVRs) {
1515 if (!DVR->isDbgValue())
1516 continue;
1517 Instruction *MarkedI = DVR->getInstruction();
1518 if (ExI && MarkedI->getParent() != ExI->getParent())
1519 continue;
1520 if (!ExI || ExI->comesBefore(MarkedI)) {
1521 DVR->replaceVariableLocationOp(&From, &To);
1522 continue;
1523 }
1524 DebugVariableAggregate Var(DVR);
1525 auto HasSameVar = [&](auto Records) {
1526 return any_of(filterDbgVars(Records),
1527 [&](const DbgVariableRecord &Other) {
1528 return DebugVariableAggregate(&Other) == Var;
1529 });
1530 };
1531 if (HasSameVar(make_range(std::next(DVR->getIterator()),
1532 MarkedI->getDbgRecordRange().end())) ||
1533 any_of(make_range(std::next(MarkedI->getIterator()),
1534 std::next(ExI->getIterator())),
1535 [&](const Instruction &I) {
1536 return HasSameVar(I.getDbgRecordRange());
1537 }))
1538 continue;
1539 DbgVariableRecord *NewDVR = DVR->clone();
1540 NewDVR->replaceVariableLocationOp(&From, &To);
1541 ExI->getParent()->insertDbgRecordAfter(NewDVR, ExI);
1542 }
1543}
1544
1545} // 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
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LLVM_ABI void replaceVariableLocationOp(Value *OldValue, Value *NewValue, bool AllowEmpty=false)
LLVM_ABI DbgVariableRecord * clone() const
Identifies a unique instance of a whole variable (discards/ignores fragment information).
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:115
iterator_range< simple_ilist< DbgRecord >::iterator > getDbgRecordRange() const
Return a range over the DbgRecords attached to this instruction.
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
self_iterator getIterator()
Definition ilist_node.h:123
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:277
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:673
bool areAllOperandsNonInsts(Value *V)
Checks if the provided value does not require scheduling.
Definition SLPUtils.cpp:457
std::optional< unsigned > getElementIndex(const Value *Inst, unsigned Offset)
Definition SLPUtils.cpp:231
bool doesInTreeUserNeedToExtract(Value *Scalar, Instruction *UserInst, TargetLibraryInfo *TLI, const TargetTransformInfo *TTI)
Definition SLPUtils.cpp:776
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:894
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:804
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:822
SmallBitVector getAltInstrMask(ArrayRef< Value * > VL, Type *ScalarTy, unsigned Opcode0, unsigned Opcode1)
SmallBitVector isUndefVector(const Value *V, const SmallBitVector &UseMask)
Checks if the given value is actually an undefined constant vector.
Definition SLPUtils.cpp:726
Intrinsic::ID getMaskedDivRemIntrinsic(unsigned Opcode)
bool isUsedOutsideBlock(Value *V)
Checks if the provided value does not require scheduling.
Definition SLPUtils.cpp:468
bool doesNotNeedToSchedule(ArrayRef< Value * > VL)
Checks if the specified array of instructions does not require scheduling.
Definition SLPUtils.cpp:486
std::optional< unsigned > getInsertExtractIndex(const Value *Inst, unsigned Offset)
Definition SLPUtils.cpp:424
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 redirectDbgValues(Instruction &From, Value &To)
The debug values of the erased From are kept on its replacement To.
void reorderScalars(SmallVectorImpl< Value * > &Scalars, ArrayRef< int > Mask)
Reorders the list of scalars in accordance with the given Mask.
Definition SLPUtils.cpp:310
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:417
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:395
bool allSameOpcode(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:259
bool isSplat(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:143
unsigned getNumElements(Type *Ty)
Definition SLPUtils.cpp:88
std::string shortBundleName(ArrayRef< Value * > VL, int Idx)
Print a short descriptor of the instruction bundle suitable for debug output.
Definition SLPUtils.cpp:105
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:96
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:203
TargetTransformInfo::TargetCostKind getSLPCostKind(const Function *F)
bool isReverseOrder(ArrayRef< unsigned > Order)
Check if Order represents reverse order.
Definition SLPUtils.cpp:374
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:862
void transformScalarShuffleIndiciesToVector(unsigned VecTyNumElements, SmallVectorImpl< int > &Mask)
Definition SLPUtils.cpp:491
SmallVector< int > calculateShufflevectorMask(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:546
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:709
bool isCommutative(const Instruction *I, const Value *ValWithUses, bool IsCopyable)
Definition SLPUtils.cpp:166
template SmallBitVector isUndefVector< false >(const Value *, const SmallBitVector &)
unsigned getNumberOfPotentiallyCommutativeOps(Instruction *I)
Definition SLPUtils.cpp:221
bool allConstant(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:137
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:301
bool allSameBlock(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:115
bool isReassocChainLink(const Instruction *I)
Definition SLPUtils.cpp:60
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:157
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:330
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:320
void addMask(SmallVectorImpl< int > &Mask, ArrayRef< int > SubMask, bool ExtendingManyInputs)
Shuffles Mask in accordance with the given SubMask.
Definition SLPUtils.cpp:951
bool isSimple(Instruction *I)
Definition SLPUtils.cpp:812
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:44
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:506
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:586
SmallVector< Constant * > replicateMask(ArrayRef< Constant * > Val, unsigned VF)
Replicates the given Val VF times.
unsigned getReassocCombineOpcode(unsigned Opcode)
Definition SLPUtils.cpp:49
bool isVectorLikeInstWithConstOps(Value *V)
Checks if V is one of vector-like instructions, i.e.
Definition SLPUtils.cpp:68
bool doesNotNeedToBeScheduled(Value *V)
Checks if the specified value does not require scheduling.
Definition SLPUtils.cpp:482
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:100
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:383
bool isConstant(Value *V)
Definition SLPUtils.cpp:40
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:702
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:976
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.
LLVM_ABI void findDbgValues(Value *V, SmallVectorImpl< DbgVariableRecord * > &DbgVariableRecords)
Finds the dbg.values describing a value.
@ 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
@ Other
Any other memory.
Definition ModRef.h:68
@ 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.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
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