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