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