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