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"
16#include "llvm/IR/Constants.h"
17#include "llvm/IR/DataLayout.h"
25
26#include <algorithm>
27#include <string>
28#include <type_traits>
29
30using namespace llvm;
31using namespace llvm::PatternMatch;
32
33namespace llvm::slpvectorizer {
34
38
39bool isBinOpIdentityConstant(const Value *V, unsigned Opcode) {
40 const auto *CI = dyn_cast<ConstantInt>(V);
41 return CI && ConstantExpr::getBinOpIdentity(Opcode, CI->getType()) == CI;
42}
43
44unsigned getReassocCombineOpcode(unsigned Opcode) {
45 switch (Opcode) {
46 case Instruction::Sub:
47 return Instruction::Add;
48 case Instruction::FSub:
49 return Instruction::FAdd;
50 default:
51 return Opcode;
52 }
53}
54
56 if (I->getOpcode() == Instruction::Sub)
57 return true;
58 if (I->getOpcode() == Instruction::FSub)
59 return I->hasAllowReassoc();
60 return I->isAssociative();
61}
62
64 auto *I = dyn_cast<Instruction>(V);
65 // Non-instructions are vector-like only if they are undef.
66 if (!I)
67 return isa<UndefValue>(V);
68 switch (I->getOpcode()) {
69 case Instruction::ExtractValue:
70 case Instruction::InsertValue:
71 return true;
72 case Instruction::ExtractElement:
73 return isa<FixedVectorType>(I->getOperand(0)->getType()) &&
74 isConstant(I->getOperand(1));
75 case Instruction::InsertElement:
76 return isa<FixedVectorType>(I->getOperand(0)->getType()) &&
77 isConstant(I->getOperand(2));
78 default:
79 return false;
80 }
81}
82
83unsigned getNumElements(Type *Ty) {
85 "ScalableVectorType is not supported.");
86 if (isVectorizedTy(Ty))
88 return 1;
89}
90
91unsigned getPartNumElems(unsigned Size, unsigned NumParts) {
92 return std::min<unsigned>(Size, bit_ceil(divideCeil(Size, NumParts)));
93}
94
95unsigned getNumElems(unsigned Size, unsigned PartNumElems, unsigned Part) {
96 return std::min<unsigned>(PartNumElems, Size - Part * PartNumElems);
97}
98
99#if !defined(NDEBUG)
100std::string shortBundleName(ArrayRef<Value *> VL, int Idx) {
101 std::string Result;
102 raw_string_ostream OS(Result);
103 if (Idx >= 0)
104 OS << "Idx: " << Idx << ", ";
105 OS << "n=" << VL.size() << " [" << *VL.front() << ", ..]";
106 return Result;
107}
108#endif
109
111 auto *It = find_if(VL, IsaPred<Instruction>);
112 if (It == VL.end())
113 return false;
116 return true;
117
118 BasicBlock *BB = I0->getParent();
119 for (Value *V : iterator_range(It, VL.end())) {
120 if (isa<PoisonValue>(V))
121 continue;
122 auto *II = dyn_cast<Instruction>(V);
123 if (!II)
124 return false;
125
126 if (BB != II->getParent())
127 return false;
128 }
129 return true;
130}
131
133 // Constant expressions and globals can't be vectorized like normal integer/FP
134 // constants.
135 return all_of(VL, isConstant);
136}
137
139 Value *FirstNonUndef = nullptr;
140 for (Value *V : VL) {
141 if (isa<UndefValue>(V))
142 continue;
143 if (!FirstNonUndef) {
144 FirstNonUndef = V;
145 continue;
146 }
147 if (V != FirstNonUndef)
148 return false;
149 }
150 return FirstNonUndef != nullptr;
151}
152
154 if (LHS == RHS)
155 return RHS;
156 if ((LHS == Intrinsic::fma || LHS == Intrinsic::fmuladd) &&
157 (RHS == Intrinsic::fma || RHS == Intrinsic::fmuladd))
158 return Intrinsic::fma;
160}
161
162bool isCommutative(const Instruction *I, const Value *ValWithUses,
163 bool IsCopyable) {
164 if (auto *Cmp = dyn_cast<CmpInst>(I))
165 return Cmp->isCommutative();
166 if (auto *BO = dyn_cast<BinaryOperator>(I))
167 return BO->isCommutative() ||
168 (BO->getOpcode() == Instruction::Sub && ValWithUses->hasUseList() &&
169 !ValWithUses->hasNUsesOrMore(UsesLimit) &&
170 all_of(
171 ValWithUses->uses(),
172 [&](const Use &U) {
173 // Commutative, if icmp eq/ne sub, 0
174 CmpPredicate Pred;
175 if (match(U.getUser(),
176 m_ICmp(Pred, m_Specific(U.get()), m_Zero())) &&
177 (Pred == ICmpInst::ICMP_EQ || Pred == ICmpInst::ICMP_NE))
178 return true;
179 // Commutative, if abs(sub nsw, true) or abs(sub, false).
180 ConstantInt *Flag;
181 auto *I = dyn_cast<BinaryOperator>(U.get());
182 return match(U.getUser(),
183 m_Intrinsic<Intrinsic::abs>(
184 m_Specific(U.get()), m_ConstantInt(Flag))) &&
185 ((!IsCopyable && I && !I->hasNoSignedWrap()) ||
186 Flag->isOne());
187 })) ||
188 (BO->getOpcode() == Instruction::FSub && ValWithUses->hasUseList() &&
189 !ValWithUses->hasNUsesOrMore(UsesLimit) &&
190 all_of(ValWithUses->uses(), [](const Use &U) {
191 return match(U.getUser(),
192 m_Intrinsic<Intrinsic::fabs>(m_Specific(U.get())));
193 }));
194 return I->isCommutative();
195}
196
197bool isCommutative(const Instruction *I) { return isCommutative(I, I); }
198
199bool isCommutableOperand(const Instruction *I, Value *ValWithUses, unsigned Op,
200 bool IsCopyable) {
201 assert(isCommutative(I, ValWithUses, IsCopyable) &&
202 "The instruction is not commutative.");
203 if (isa<CmpInst>(I))
204 return true;
205 if (auto *BO = dyn_cast<BinaryOperator>(I)) {
206 switch (BO->getOpcode()) {
207 case Instruction::Sub:
208 case Instruction::FSub:
209 return true;
210 default:
211 break;
212 }
213 }
214 return I->isCommutableOperand(Op);
215}
216
219 // IntrinsicInst::isCommutative returns true if swapping the first "two"
220 // arguments to the intrinsic produces the same result.
221 constexpr unsigned IntrinsicNumOperands = 2;
222 return IntrinsicNumOperands;
223 }
224 return I->getNumOperands();
225}
226
227std::optional<unsigned> getElementIndex(const Value *Inst, unsigned Offset) {
228 if (auto Index = getInsertExtractIndex<InsertElementInst>(Inst, Offset))
229 return Index;
231 return Index;
232
233 unsigned Index = Offset;
234
235 const auto *IV = dyn_cast<InsertValueInst>(Inst);
236 if (!IV)
237 return std::nullopt;
238
239 Type *CurrentType = IV->getType();
240 for (unsigned I : IV->indices()) {
241 if (const auto *ST = dyn_cast<StructType>(CurrentType)) {
242 Index *= ST->getNumElements();
243 CurrentType = ST->getElementType(I);
244 } else if (const auto *AT = dyn_cast<ArrayType>(CurrentType)) {
245 Index *= AT->getNumElements();
246 CurrentType = AT->getElementType();
247 } else {
248 return std::nullopt;
249 }
250 Index += I;
251 }
252 return Index;
253}
254
256 auto *It = find_if(VL, IsaPred<Instruction>);
257 if (It == VL.end())
258 return true;
259 Instruction *MainOp = cast<Instruction>(*It);
260 unsigned Opcode = MainOp->getOpcode();
261 bool IsCmpOp = isa<CmpInst>(MainOp);
262 CmpInst::Predicate BasePred = IsCmpOp ? cast<CmpInst>(MainOp)->getPredicate()
264 return all_of(make_range(It, VL.end()), [&](Value *V) {
265 if (auto *CI = dyn_cast<CmpInst>(V))
266 return BasePred == CI->getPredicate();
267 if (auto *I = dyn_cast<Instruction>(V))
268 return I->getOpcode() == Opcode;
269 return isa<PoisonValue>(V);
270 });
271}
272
273std::optional<unsigned> getExtractIndex(const Instruction *E) {
274 unsigned Opcode = E->getOpcode();
275 assert((Opcode == Instruction::ExtractElement ||
276 Opcode == Instruction::ExtractValue) &&
277 "Expected extractelement or extractvalue instruction.");
278 if (Opcode == Instruction::ExtractElement) {
279 auto *CI = dyn_cast<ConstantInt>(E->getOperand(1));
280 if (!CI)
281 return std::nullopt;
282 // Check if the index is out of bound. We can get the source vector from
283 // operand 0.
284 unsigned Idx = CI->getZExtValue();
285 auto *EE = cast<ExtractElementInst>(E);
286 const unsigned VF = getNumElements(EE->getVectorOperandType());
287 if (Idx >= VF)
288 return std::nullopt;
289 return Idx;
290 }
291 auto *EI = cast<ExtractValueInst>(E);
292 if (EI->getNumIndices() != 1)
293 return std::nullopt;
294 return *EI->idx_begin();
295}
296
298 SmallVectorImpl<int> &Mask) {
299 Mask.clear();
300 const unsigned E = Indices.size();
301 Mask.resize(E, PoisonMaskElem);
302 for (unsigned I = 0; I < E; ++I)
303 Mask[Indices[I]] = I;
304}
305
307 assert(!Mask.empty() && "Expected non-empty mask.");
308 SmallVector<Value *> Prev(Scalars.size(),
309 PoisonValue::get(Scalars.front()->getType()));
310 Prev.swap(Scalars);
311 for (unsigned I = 0, E = Prev.size(); I < E; ++I)
312 if (Mask[I] != PoisonMaskElem)
313 Scalars[Mask[I]] = Prev[I];
314}
315
317 assert(!VL.empty() && "Expected non-empty list of values.");
318 Type *Ty = VL.consume_front()->getType();
319 return all_of(VL, [&](Value *V) { return V->getType() == Ty; });
320}
321
322template <typename T>
323std::optional<unsigned> getInsertExtractIndex(const Value *Inst,
324 unsigned Offset) {
325 static_assert(std::is_same_v<T, InsertElementInst> ||
326 std::is_same_v<T, ExtractElementInst>,
327 "unsupported T");
328 const auto *IE = dyn_cast<T>(Inst);
329 if (!IE)
330 return std::nullopt;
331 // InsertElement: result is the vector, index is op 2.
332 // ExtractElement: result is scalar, vector is op 0, index is op 1.
333 constexpr bool IsInsert = std::is_same_v<T, InsertElementInst>;
334 Type *VecTy = IsInsert ? IE->getType() : IE->getOperand(0)->getType();
335 const auto *VT = dyn_cast<FixedVectorType>(VecTy);
336 if (!VT)
337 return std::nullopt;
338 const auto *CI = dyn_cast<ConstantInt>(IE->getOperand(IsInsert ? 2 : 1));
339 if (!CI)
340 return std::nullopt;
341 if (CI->getValue().uge(VT->getNumElements()))
342 return std::nullopt;
343 unsigned Index = Offset;
344 Index *= VT->getNumElements();
345 Index += CI->getZExtValue();
346 return Index;
347}
348
349// Only these two specializations are used; instantiate them here so the
350// definition can stay out of the header.
351template std::optional<unsigned>
353template std::optional<unsigned>
355
357 auto *I = dyn_cast<Instruction>(V);
358 if (!I)
359 return true;
360 return !mayHaveNonDefUseDependency(*I) &&
361 all_of(I->operands(), [I](Value *V) {
362 auto *IO = dyn_cast<Instruction>(V);
363 if (!IO)
364 return true;
365 return isa<PHINode>(IO) || IO->getParent() != I->getParent();
366 });
367}
368
370 auto *I = dyn_cast<Instruction>(V);
371 if (!I)
372 return true;
373 // Limits the number of uses to save compile time.
374 return !I->mayReadOrWriteMemory() && !I->hasNUsesOrMore(UsesLimit) &&
375 all_of(I->users(), [I](User *U) {
376 auto *IU = dyn_cast<Instruction>(U);
377 if (!IU)
378 return true;
379 return IU->getParent() != I->getParent() || isa<PHINode>(IU);
380 });
381}
382
386
391
392void transformScalarShuffleIndiciesToVector(unsigned VecTyNumElements,
393 SmallVectorImpl<int> &Mask) {
394 // The ShuffleBuilder implementation use shufflevector to splat an "element".
395 // But the element have different meaning for SLP (scalar) and REVEC
396 // (vector). We need to expand Mask into masks which shufflevector can use
397 // directly.
398 SmallVector<int> NewMask(Mask.size() * VecTyNumElements);
399 for (unsigned I : seq<unsigned>(Mask.size()))
400 for (auto [J, MaskV] : enumerate(MutableArrayRef(NewMask).slice(
401 I * VecTyNumElements, VecTyNumElements)))
402 MaskV = Mask[I] == PoisonMaskElem ? PoisonMaskElem
403 : Mask[I] * VecTyNumElements + J;
404 Mask.swap(NewMask);
405}
406
408 if (VL.empty())
409 return 0;
411 return 0;
412 auto *SV = cast<ShuffleVectorInst>(VL.front());
413 unsigned SVNumElements =
414 cast<FixedVectorType>(SV->getOperand(0)->getType())->getNumElements();
415 unsigned ShuffleMaskSize = SV->getShuffleMask().size();
416 if (SVNumElements % ShuffleMaskSize != 0)
417 return 0;
418 unsigned GroupSize = SVNumElements / ShuffleMaskSize;
419 if (GroupSize == 0 || (VL.size() % GroupSize) != 0)
420 return 0;
421 unsigned NumGroup = 0;
422 for (size_t I = 0, E = VL.size(); I != E; I += GroupSize) {
423 auto *SV = cast<ShuffleVectorInst>(VL[I]);
424 Value *Src = SV->getOperand(0);
425 ArrayRef<Value *> Group = VL.slice(I, GroupSize);
426 SmallBitVector ExpectedIndex(GroupSize);
427 if (!all_of(Group, [&](Value *V) {
428 auto *SV = cast<ShuffleVectorInst>(V);
429 // From the same source.
430 if (SV->getOperand(0) != Src)
431 return false;
432 int Index;
433 if (!SV->isExtractSubvectorMask(Index))
434 return false;
435 ExpectedIndex.set(Index / ShuffleMaskSize);
436 return true;
437 }))
438 return 0;
439 if (!ExpectedIndex.all())
440 return 0;
441 ++NumGroup;
442 }
443 assert(NumGroup == (VL.size() / GroupSize) && "Unexpected number of groups");
444 return NumGroup;
445}
446
448 assert(getShufflevectorNumGroups(VL) && "Not supported shufflevector usage.");
449 auto *SV = cast<ShuffleVectorInst>(VL.front());
450 unsigned SVNumElements =
451 cast<FixedVectorType>(SV->getOperand(0)->getType())->getNumElements();
452 SmallVector<int> Mask;
453 unsigned AccumulateLength = 0;
454 for (Value *V : VL) {
455 auto *SV = cast<ShuffleVectorInst>(V);
456 for (int M : SV->getShuffleMask())
457 Mask.push_back(M == PoisonMaskElem ? PoisonMaskElem
458 : AccumulateLength + M);
459 AccumulateLength += SVNumElements;
460 }
461 return Mask;
462}
463
465 SmallBitVector UseMask(VF, true);
466 for (auto [Idx, Value] : enumerate(Mask)) {
467 if (Value == PoisonMaskElem) {
468 if (MaskArg == UseMask::UndefsAsMask)
469 UseMask.reset(Idx);
470 continue;
471 }
472 if (MaskArg == UseMask::FirstArg && Value < VF)
473 UseMask.reset(Value);
474 else if (MaskArg == UseMask::SecondArg && Value >= VF)
475 UseMask.reset(Value - VF);
476 }
477 return UseMask;
478}
479
480template <bool IsPoisonOnly>
482 SmallBitVector Res(UseMask.empty() ? 1 : UseMask.size(), true);
483 using T = std::conditional_t<IsPoisonOnly, PoisonValue, UndefValue>;
484 if (isa<T>(V))
485 return Res;
486 auto *VecTy = dyn_cast<FixedVectorType>(V->getType());
487 if (!VecTy)
488 return Res.reset();
489 auto *C = dyn_cast<Constant>(V);
490 if (!C) {
491 if (!UseMask.empty()) {
492 const Value *Base = V;
493 while (auto *II = dyn_cast<InsertElementInst>(Base)) {
494 Base = II->getOperand(0);
495 if (isa<T>(II->getOperand(1)))
496 continue;
497 std::optional<unsigned> Idx = getElementIndex(II);
498 if (!Idx) {
499 Res.reset();
500 return Res;
501 }
502 if (*Idx < UseMask.size() && !UseMask.test(*Idx))
503 Res.reset(*Idx);
504 }
505 // TODO: Add analysis for shuffles here too.
506 if (V == Base) {
507 Res.reset();
508 } else {
509 SmallBitVector SubMask(UseMask.size(), false);
510 Res &= isUndefVector<IsPoisonOnly>(Base, SubMask);
511 }
512 } else {
513 Res.reset();
514 }
515 return Res;
516 }
517 for (unsigned I = 0, E = VecTy->getNumElements(); I != E; ++I) {
518 if (Constant *Elem = C->getAggregateElement(I))
519 if (!isa<T>(Elem) &&
520 (UseMask.empty() || (I < UseMask.size() && !UseMask.test(I))))
521 Res.reset(I);
522 }
523 return Res;
524}
525
527 const SmallBitVector &);
529 const SmallBitVector &);
530
533 const TargetTransformInfo *TTI) {
534 if (!UserInst)
535 return false;
536 unsigned Opcode = UserInst->getOpcode();
537 switch (Opcode) {
538 case Instruction::Load: {
539 LoadInst *LI = cast<LoadInst>(UserInst);
540 return (LI->getPointerOperand() == Scalar);
541 }
542 case Instruction::Store: {
543 StoreInst *SI = cast<StoreInst>(UserInst);
544 return (SI->getPointerOperand() == Scalar);
545 }
546 case Instruction::Call: {
547 CallInst *CI = cast<CallInst>(UserInst);
549 return any_of(enumerate(CI->args()), [&](auto &&Arg) {
550 return isVectorIntrinsicWithScalarOpAtArg(ID, Arg.index(), TTI) &&
551 Arg.value().get() == Scalar;
552 });
553 }
554 default:
555 return false;
556 }
557}
558
566
568 if (LoadInst *LI = dyn_cast<LoadInst>(I))
569 return LI->isSimple();
571 return SI->isSimple();
573 return !MI->isVolatile();
574 return true;
575}
576
577bool isSelectedBaseLoad(Type *ScalarTy, ArrayRef<Value *> PointerOps,
578 const DataLayout &DL, Value *&TrueBase,
579 Value *&FalseBase,
580 SmallVectorImpl<Value *> &Conditions) {
581 TrueBase = nullptr;
582 FalseBase = nullptr;
583 uint64_t ScalarSize = DL.getTypeStoreSize(ScalarTy);
584 Conditions.assign(PointerOps.size(), nullptr);
585 for (auto [Idx, P] : enumerate(PointerOps)) {
586 Value *Base = P;
587 uint64_t Offset = 0;
588 if (auto *GEP = dyn_cast<GetElementPtrInst>(P)) {
589 APInt OffsetAP(DL.getIndexTypeSizeInBits(GEP->getType()), 0);
590 if (!GEP->accumulateConstantOffset(DL, OffsetAP) || OffsetAP.isNegative())
591 return false;
592 Offset = OffsetAP.getZExtValue();
593 Base = GEP->getPointerOperand();
594 }
595 auto *Sel = dyn_cast<SelectInst>(Base);
596 if (!Sel)
597 return false;
598 Value *T = Sel->getTrueValue();
599 Value *F = Sel->getFalseValue();
600 if (!TrueBase) {
601 if (T == F)
602 return false;
603 TrueBase = T;
604 FalseBase = F;
605 } else if (TrueBase != T || FalseBase != F) {
606 return false;
607 }
608 // Lane Idx must be at exactly Base + Idx * sizeof(ScalarTy); codegen reads
609 // contiguously from TrueBase/FalseBase starting at lane 0.
610 if (Offset != static_cast<uint64_t>(Idx) * ScalarSize)
611 return false;
612 Conditions[Idx] = Sel->getCondition();
613 }
614 return TrueBase != nullptr;
615}
616
618 bool ExtendingManyInputs) {
619 if (SubMask.empty())
620 return;
621 assert(
622 (!ExtendingManyInputs || SubMask.size() > Mask.size() ||
623 // Check if input scalars were extended to match the size of other node.
624 (SubMask.size() == Mask.size() && Mask.back() == PoisonMaskElem)) &&
625 "SubMask with many inputs support must be larger than the mask.");
626 if (Mask.empty()) {
627 Mask.append(SubMask.begin(), SubMask.end());
628 return;
629 }
630 SmallVector<int> NewMask(SubMask.size(), PoisonMaskElem);
631 int TermValue = std::min(Mask.size(), SubMask.size());
632 for (int I = 0, E = SubMask.size(); I < E; ++I) {
633 if (SubMask[I] == PoisonMaskElem ||
634 (!ExtendingManyInputs &&
635 (SubMask[I] >= TermValue || Mask[SubMask[I]] >= TermValue)))
636 continue;
637 NewMask[I] = Mask[SubMask[I]];
638 }
639 Mask.swap(NewMask);
640}
641
643 const size_t Sz = Order.size();
644 SmallBitVector UnusedIndices(Sz, /*t=*/true);
645 SmallBitVector MaskedIndices(Sz);
646 for (unsigned I = 0; I < Sz; ++I) {
647 if (Order[I] < Sz)
648 UnusedIndices.reset(Order[I]);
649 else
650 MaskedIndices.set(I);
651 }
652 if (MaskedIndices.none())
653 return;
654 assert(UnusedIndices.count() == MaskedIndices.count() &&
655 "Non-synced masked/available indices.");
656 int Idx = UnusedIndices.find_first();
657 int MIdx = MaskedIndices.find_first();
658 while (MIdx >= 0) {
659 assert(Idx >= 0 && "Indices must be synced.");
660 Order[MIdx] = Idx;
661 Idx = UnusedIndices.find_next(Idx);
662 MIdx = MaskedIndices.find_next(MIdx);
663 }
664}
665
667 unsigned Opcode0, unsigned Opcode1) {
668 unsigned ScalarTyNumElements = getNumElements(ScalarTy);
669 SmallBitVector OpcodeMask(VL.size() * ScalarTyNumElements, false);
670 for (unsigned Lane : seq<unsigned>(VL.size())) {
671 if (isa<PoisonValue>(VL[Lane]))
672 continue;
673 if (cast<Instruction>(VL[Lane])->getOpcode() == Opcode1)
674 OpcodeMask.set(Lane * ScalarTyNumElements,
675 Lane * ScalarTyNumElements + ScalarTyNumElements);
676 }
677 return OpcodeMask;
678}
679
681 assert(none_of(Val, [](Constant *C) { return C->getType()->isVectorTy(); }) &&
682 "Expected scalar constants.");
683 SmallVector<Constant *> NewVal(Val.size() * VF);
684 for (auto [I, V] : enumerate(Val))
685 std::fill_n(NewVal.begin() + I * VF, VF, V);
686 return NewVal;
687}
688
690 switch (Opcode) {
691 case Instruction::UDiv:
692 return Intrinsic::masked_udiv;
693 case Instruction::SDiv:
694 return Intrinsic::masked_sdiv;
695 case Instruction::URem:
696 return Intrinsic::masked_urem;
697 case Instruction::SRem:
698 return Intrinsic::masked_srem;
699 default:
700 llvm_unreachable("Unexpected opcode");
701 }
702}
703
704/// Returns true if \p I is a part of a single-use chain, computing an address,
705/// which does not pay off the vectorization: a constant table is accessed by a
706/// gather, while the indices, unrelated between the lanes, require a full
707/// buildvector, unlike the ones, shifted by a constant from a common base.
708static bool isNonProfitableIndex(const Instruction *I) {
709 constexpr unsigned MaxIndexChainLength = 3;
710 // A constant shift of a common base is a cheap buildvector, while the loads
711 // are vectorized together with the indices, computed from them.
712 auto IsProfitableOperand = [](const Value *V) {
713 if (isa<Constant>(V))
714 return true;
715 if (const auto *Cast = dyn_cast<CastInst>(V); Cast && Cast->hasOneUse())
716 V = Cast->getOperand(0);
717 return isa<LoadInst>(V);
718 };
719 const User *U = I->user_back();
720 for ([[maybe_unused]] unsigned _ : seq<unsigned>(MaxIndexChainLength)) {
721 if (const auto *GEP = dyn_cast<GetElementPtrInst>(U))
722 return isa<Constant>(GEP->getPointerOperand()) ||
723 none_of(I->operand_values(), IsProfitableOperand);
724 if (!isa<Instruction>(U) || !U->hasOneUse())
725 return false;
726 U = U->user_back();
727 }
728 return false;
729}
730
732 if (!I->hasOneUse() || isNonProfitableIndex(I))
733 return false;
734 // The operation with the identity or the absorbing constant is folded away
735 // before the codegen, the vector node only repacks the lanes.
736 if (const auto *BO = dyn_cast<BinaryOperator>(I)) {
737 unsigned Opcode = BO->getOpcode();
738 Type *Ty = BO->getType();
739 for (unsigned Idx : seq<unsigned>(2)) {
740 const auto *C = dyn_cast<Constant>(BO->getOperand(Idx));
742 Opcode, Ty, /*AllowRHSConstant=*/Idx == 1) ||
744 Opcode, Ty, /*AllowLHSConstant=*/Idx == 0)))
745 return false;
746 }
747 }
748 const User *U = I->user_back();
751 if (isa<CastInst>(I))
753 (!isa<CastInst>(U) || U->hasOneUse());
755 I);
756}
757
758Instruction *lookThroughCastRoundTrip(Value *V, bool MustBeElidable) {
759 auto *Wide = dyn_cast<FPExtInst>(V);
760 if (!Wide || !Wide->hasOneUse())
761 return nullptr;
762 auto *Narrow = dyn_cast<FPTruncInst>(Wide->getOperand(0));
763 if (!Narrow || !Narrow->hasOneUse())
764 return nullptr;
765 Value *Src = Narrow->getOperand(0);
766 if (!isa<Instruction>(Src) || Src->getType() != Wide->getType())
767 return nullptr;
768 if (MustBeElidable && !(Wide->hasAllowContract() && Wide->hasNoNaNs() &&
769 Wide->hasNoInfs() && Narrow->hasAllowContract()))
770 return nullptr;
771 return Narrow;
772}
773
774namespace {
775
776/// Shifts and the mask accumulated from the narrow ops on the current path:
777/// the shifts above and at the narrow level, the bitwidth of the narrow ops
778/// (0 if none) and the mask from the absorbed narrow ands.
779struct NarrowedChainState {
780 unsigned Shift = 0;
781 unsigned NarrowShift = 0;
782 unsigned NarrowBW = 0;
783 APInt NarrowMask = APInt(1, 0);
784
785 /// The mask for the absorbed narrow ops in the leaf type, applied before
786 /// widening and shifting; all-ones if nothing was absorbed.
787 APInt getMask(unsigned LeafBW) const {
788 if (NarrowBW == 0)
789 return APInt::getAllOnes(LeafBW);
790 return (NarrowMask & (APInt::getAllOnes(NarrowBW) << NarrowShift))
791 .lshr(NarrowShift)
792 .trunc(LeafBW);
793 }
794};
795
796} // namespace
797
798static void
799collectNarrowedLeavesImpl(Value *V, unsigned RdxOpcode, unsigned WideBW,
800 NarrowedChainState S, unsigned Depth,
801 unsigned MaxDepth,
803 SmallVectorImpl<Instruction *> &ChainInsts) {
804 if (Depth < MaxDepth) {
805 if (auto *Z = dyn_cast<ZExtInst>(V);
806 Z && Z->getSrcTy()->isIntegerTy() && !Z->getSrcTy()->isIntegerTy(1)) {
807 ChainInsts.push_back(Z);
808 return collectNarrowedLeavesImpl(Z->getOperand(0), RdxOpcode, WideBW, S,
809 Depth + 1, MaxDepth, Leaves, ChainInsts);
810 }
811 if (auto *BO = dyn_cast<BinaryOperator>(V)) {
812 if (BO->getOpcode() == RdxOpcode) {
813 ChainInsts.push_back(BO);
814 collectNarrowedLeavesImpl(BO->getOperand(0), RdxOpcode, WideBW, S,
815 Depth + 1, MaxDepth, Leaves, ChainInsts);
816 collectNarrowedLeavesImpl(BO->getOperand(1), RdxOpcode, WideBW, S,
817 Depth + 1, MaxDepth, Leaves, ChainInsts);
818 return;
819 }
820 const APInt *Amt;
821 unsigned BW = V->getType()->getScalarSizeInBits();
822 auto *Z = dyn_cast<ZExtInst>(BO->getOperand(0));
823 if (BO->getOpcode() == Instruction::Shl && Z && S.NarrowBW == 0 &&
824 match(BO->getOperand(1), m_APInt(Amt)) && Amt->ult(BW) &&
825 Z->getSrcTy()->isIntegerTy() && !Z->getSrcTy()->isIntegerTy(1) &&
826 (BW == WideBW ||
827 Z->getSrcTy()->getIntegerBitWidth() + Amt->getZExtValue() <= BW) &&
828 S.Shift + Amt->getZExtValue() < WideBW) {
829 ChainInsts.push_back(BO);
830 ChainInsts.push_back(Z);
831 S.Shift += Amt->getZExtValue();
832 return collectNarrowedLeavesImpl(Z->getOperand(0), RdxOpcode, WideBW, S,
833 Depth + 1, MaxDepth, Leaves,
834 ChainInsts);
835 }
836 // Narrow shls fold into the shift and narrow ands into the mask; the
837 // mask clears the bits the shls shift out. Only same-width ops compose
838 // on one path, and the combined shift must stay a valid shift amount in
839 // both types.
840 if (BW < WideBW && (S.NarrowBW == 0 || BW == S.NarrowBW)) {
841 if (BO->getOpcode() == Instruction::Shl &&
842 match(BO->getOperand(1), m_APInt(Amt)) && Amt->ult(BW) &&
843 S.NarrowShift + Amt->getZExtValue() < BW &&
844 S.Shift + S.NarrowShift + Amt->getZExtValue() < WideBW) {
845 ChainInsts.push_back(BO);
846 if (BO->hasNoUnsignedWrap() && S.NarrowBW == 0) {
847 S.Shift += Amt->getZExtValue();
848 // Lossless shls shift out only known-zero bits; record them as
849 // the mask so matching lanes can form a splat.
850 S.NarrowBW = BW;
851 S.NarrowMask = APInt::getLowBitsSet(BW, BW - Amt->getZExtValue());
852 } else {
853 if (S.NarrowBW == 0) {
854 S.NarrowBW = BW;
855 S.NarrowMask = APInt::getAllOnes(BW);
856 }
857 S.NarrowShift += Amt->getZExtValue();
858 }
859 return collectNarrowedLeavesImpl(BO->getOperand(0), RdxOpcode, WideBW,
860 S, Depth + 1, MaxDepth, Leaves,
861 ChainInsts);
862 }
863 Value *X;
864 if (match(BO, m_c_And(m_Value(X), m_APInt(Amt)))) {
865 ChainInsts.push_back(BO);
866 if (S.NarrowBW == 0) {
867 S.NarrowBW = BW;
868 S.NarrowMask = APInt::getAllOnes(BW);
869 }
870 S.NarrowMask &= *Amt << S.NarrowShift;
871 return collectNarrowedLeavesImpl(X, RdxOpcode, WideBW, S, Depth + 1,
872 MaxDepth, Leaves, ChainInsts);
873 }
874 }
875 }
876 }
877 Leaves.emplace_back(V, S.Shift + S.NarrowShift,
878 S.getMask(V->getType()->getScalarSizeInBits()));
879}
880
881void collectNarrowedLeaves(Value *V, unsigned RdxOpcode, unsigned WideBW,
882 unsigned MaxDepth,
884 SmallVectorImpl<Instruction *> &ChainInsts) {
885 collectNarrowedLeavesImpl(V, RdxOpcode, WideBW, NarrowedChainState(),
886 /*Depth=*/0, MaxDepth, Leaves, ChainInsts);
887}
888
890 assert(F && "Expected function.");
891 return F->hasOptSize() ? TTI::TCK_CodeSize : TTI::TCK_RecipThroughput;
892}
893
894} // namespace llvm::slpvectorizer
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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:856
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Hexagon Common GEP
#define _
IRTranslator LLVM IR MI
static std::pair< Value *, APInt > getMask(Value *WideMask, unsigned Factor, ElementCount LeafValueEC)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
uint64_t IntrinsicInst * II
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
Provides some synthesis utilities to produce sequences of values.
static const uint32_t IV[8]
Definition blake3_impl.h:83
Class for arbitrary precision integers.
Definition APInt.h:78
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
Definition APInt.h:231
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1561
bool ult(const APInt &RHS) const
Unsigned less than comparison.
Definition APInt.h:1116
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:326
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:303
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
iterator end() const
Definition ArrayRef.h:130
size_t size() const
Get the array size.
Definition ArrayRef.h:141
iterator begin() const
Definition ArrayRef.h:129
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
Definition ArrayRef.h:185
const T & consume_front()
consume_front() - Returns the first element and drops it from ArrayRef.
Definition ArrayRef.h:156
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
This class represents a function call, abstracting a target machine's calling convention.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
static LLVM_ABI Constant * getBinOpAbsorber(unsigned Opcode, Type *Ty, bool AllowLHSConstant=false)
Return the absorbing element for the given binary operation, i.e.
static LLVM_ABI Constant * getBinOpIdentity(unsigned Opcode, Type *Ty, bool AllowRHSConstant=false, bool NSZ=false)
Return the identity constant for a binary opcode.
This is an important base class in LLVM.
Definition Constant.h:43
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
An instruction for reading from memory.
Value * getPointerOperand()
This is the common base class for memset/memcpy/memmove.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
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()
int find_next(unsigned Prev) const
Returns the index of the next set bit following the "Prev" bit.
bool all() const
Returns true if all bits are set.
size_type count() const
Returns the number of bits which are set.
SmallBitVector & reset()
bool none() const
Returns true if none of the bits are set.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void swap(SmallVectorImpl &RHS)
void 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.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
bool hasUseList() const
Check if this Value has a use-list.
Definition Value.h:344
LLVM_ABI bool hasNUsesOrMore(unsigned N) const
Return true if this value has N uses or more.
Definition Value.cpp:155
iterator_range< use_iterator > uses()
Definition Value.h:380
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
const ParentTy * getParent() const
Definition ilist_node.h:34
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
BinaryOp_match< LHS, RHS, Instruction::And, true > m_c_And(const LHS &L, const RHS &R)
Matches an And with LHS and RHS in either order.
bool match(Val *V, const Pattern &P)
auto m_Value()
Match an arbitrary value and ignore it.
A private "module" namespace for types and utilities used by this pass.
std::optional< unsigned > getExtractIndex(const Instruction *E)
Definition SLPUtils.cpp:273
template SmallBitVector isUndefVector< true >(const Value *, const SmallBitVector &)
bool areAllOperandsNonInsts(Value *V)
Checks if the provided value does not require scheduling.
Definition SLPUtils.cpp:356
std::optional< unsigned > getElementIndex(const Value *Inst, unsigned Offset)
Definition SLPUtils.cpp:227
bool doesInTreeUserNeedToExtract(Value *Scalar, Instruction *UserInst, TargetLibraryInfo *TLI, const TargetTransformInfo *TTI)
Definition SLPUtils.cpp:531
MemoryLocation getLocation(Instruction *I)
Definition SLPUtils.cpp:559
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:577
SmallBitVector getAltInstrMask(ArrayRef< Value * > VL, Type *ScalarTy, unsigned Opcode0, unsigned Opcode1)
Definition SLPUtils.cpp:666
SmallBitVector isUndefVector(const Value *V, const SmallBitVector &UseMask)
Checks if the given value is actually an undefined constant vector.
Definition SLPUtils.cpp:481
Intrinsic::ID getMaskedDivRemIntrinsic(unsigned Opcode)
Definition SLPUtils.cpp:689
bool isUsedOutsideBlock(Value *V)
Checks if the provided value does not require scheduling.
Definition SLPUtils.cpp:369
bool doesNotNeedToSchedule(ArrayRef< Value * > VL)
Checks if the specified array of instructions does not require scheduling.
Definition SLPUtils.cpp:387
std::optional< unsigned > getInsertExtractIndex(const Value *Inst, unsigned Offset)
Definition SLPUtils.cpp:323
void reorderScalars(SmallVectorImpl< Value * > &Scalars, ArrayRef< int > Mask)
Reorders the list of scalars in accordance with the given Mask.
Definition SLPUtils.cpp:306
bool allSameType(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:316
bool allSameOpcode(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:255
bool isSplat(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:138
unsigned getNumElements(Type *Ty)
Definition SLPUtils.cpp:83
std::string shortBundleName(ArrayRef< Value * > VL, int Idx)
Print a short descriptor of the instruction bundle suitable for debug output.
Definition SLPUtils.cpp:100
bool isOnceUsedSeed(const Instruction *I)
Returns true if I forms a vectorizable bundle on its own and its single user does not tear the vector...
Definition SLPUtils.cpp:731
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:91
bool isCommutableOperand(const Instruction *I, Value *ValWithUses, unsigned Op, bool IsCopyable)
Checks if the operand is commutative.
Definition SLPUtils.cpp:199
TargetTransformInfo::TargetCostKind getSLPCostKind(const Function *F)
Definition SLPUtils.cpp:889
void transformScalarShuffleIndiciesToVector(unsigned VecTyNumElements, SmallVectorImpl< int > &Mask)
Definition SLPUtils.cpp:392
SmallVector< int > calculateShufflevectorMask(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:447
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:464
bool isCommutative(const Instruction *I, const Value *ValWithUses, bool IsCopyable)
Definition SLPUtils.cpp:162
template SmallBitVector isUndefVector< false >(const Value *, const SmallBitVector &)
unsigned getNumberOfPotentiallyCommutativeOps(Instruction *I)
Definition SLPUtils.cpp:217
bool allConstant(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:132
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:297
bool allSameBlock(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:110
bool isReassocChainLink(const Instruction *I)
Definition SLPUtils.cpp:55
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:153
UseMask
Specifies the way the mask should be analyzed for undefs/poisonous elements in the shuffle mask.
Definition SLPUtils.h:241
@ SecondArg
The mask is expected to be for permutation of 2 vectors, check for the mask elements for the second a...
Definition SLPUtils.h:245
@ UndefsAsMask
Consider undef mask elements (-1) as placeholders for future shuffle elements and mark them as ones a...
Definition SLPUtils.h:248
@ FirstArg
The mask is expected to be for permutation of 1-2 vectors, check for the mask elements for the first ...
Definition SLPUtils.h:242
static void collectNarrowedLeavesImpl(Value *V, unsigned RdxOpcode, unsigned WideBW, NarrowedChainState S, unsigned Depth, unsigned MaxDepth, SmallVectorImpl< NarrowedLeafInfo > &Leaves, SmallVectorImpl< Instruction * > &ChainInsts)
Definition SLPUtils.cpp:799
void addMask(SmallVectorImpl< int > &Mask, ArrayRef< int > SubMask, bool ExtendingManyInputs)
Shuffles Mask in accordance with the given SubMask.
Definition SLPUtils.cpp:617
bool isSimple(Instruction *I)
Definition SLPUtils.cpp:567
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,...
Definition SLPUtils.cpp:758
bool isBinOpIdentityConstant(const Value *V, unsigned Opcode)
Definition SLPUtils.cpp:39
unsigned getShufflevectorNumGroups(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:407
SmallVector< Constant * > replicateMask(ArrayRef< Constant * > Val, unsigned VF)
Replicates the given Val VF times.
Definition SLPUtils.cpp:680
unsigned getReassocCombineOpcode(unsigned Opcode)
Definition SLPUtils.cpp:44
bool isVectorLikeInstWithConstOps(Value *V)
Checks if V is one of vector-like instructions, i.e.
Definition SLPUtils.cpp:63
bool doesNotNeedToBeScheduled(Value *V)
Checks if the specified value does not require scheduling.
Definition SLPUtils.cpp:383
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:95
constexpr int UsesLimit
Limit of the number of uses for potentially transformed instructions/values, used in checks to avoid ...
Definition SLPUtils.h:43
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.
Definition SLPUtils.cpp:881
bool isConstant(Value *V)
Definition SLPUtils.cpp:35
static bool isNonProfitableIndex(const Instruction *I)
Returns true if I is a part of a single-use chain, computing an address, which does not pay off the v...
Definition SLPUtils.cpp:708
template std::optional< unsigned > getInsertExtractIndex< ExtractElementInst >(const Value *, unsigned)
void fixupOrderingIndices(MutableArrayRef< unsigned > Order)
Order may have elements assigned special value (size) which is out of bounds.
Definition SLPUtils.cpp:642
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
LLVM_ABI Intrinsic::ID getVectorIntrinsicIDForCall(const CallInst *CI, const TargetLibraryInfo *TLI)
Returns intrinsic ID for call.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool isVectorizedTy(Type *Ty)
Returns true if Ty is a vector type or a struct of vector types where all vector types share the same...
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
Definition bit.h:362
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
ElementCount getVectorizedTypeVF(Type *Ty)
Returns the number of vector elements for a vectorized type.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1753
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr int PoisonMaskElem
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:395
TargetTransformInfo TTI
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1772
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
LLVM_ABI bool 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