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/STLExtras.h"
12#include "llvm/ADT/Sequence.h"
15#include "llvm/IR/Constants.h"
16#include "llvm/IR/DataLayout.h"
24
25#include <algorithm>
26#include <string>
27#include <type_traits>
28
29using namespace llvm;
30using namespace llvm::PatternMatch;
31
32namespace llvm::slpvectorizer {
33
37
38bool isBinOpIdentityConstant(const Value *V, unsigned Opcode) {
39 const auto *CI = dyn_cast<ConstantInt>(V);
40 return CI && ConstantExpr::getBinOpIdentity(Opcode, CI->getType()) == CI;
41}
42
43unsigned getReassocCombineOpcode(unsigned Opcode) {
44 switch (Opcode) {
45 case Instruction::Sub:
46 return Instruction::Add;
47 case Instruction::FSub:
48 return Instruction::FAdd;
49 default:
50 return Opcode;
51 }
52}
53
55 if (I->getOpcode() == Instruction::Sub)
56 return true;
57 if (I->getOpcode() == Instruction::FSub)
58 return I->hasAllowReassoc();
59 return I->isAssociative();
60}
61
63 auto *I = dyn_cast<Instruction>(V);
64 // Non-instructions are vector-like only if they are undef.
65 if (!I)
66 return isa<UndefValue>(V);
67 switch (I->getOpcode()) {
68 case Instruction::ExtractValue:
69 case Instruction::InsertValue:
70 return true;
71 case Instruction::ExtractElement:
72 return isa<FixedVectorType>(I->getOperand(0)->getType()) &&
73 isConstant(I->getOperand(1));
74 case Instruction::InsertElement:
75 return isa<FixedVectorType>(I->getOperand(0)->getType()) &&
76 isConstant(I->getOperand(2));
77 default:
78 return false;
79 }
80}
81
82unsigned getNumElements(Type *Ty) {
84 "ScalableVectorType is not supported.");
85 if (isVectorizedTy(Ty))
87 return 1;
88}
89
90unsigned getPartNumElems(unsigned Size, unsigned NumParts) {
91 return std::min<unsigned>(Size, bit_ceil(divideCeil(Size, NumParts)));
92}
93
94unsigned getNumElems(unsigned Size, unsigned PartNumElems, unsigned Part) {
95 return std::min<unsigned>(PartNumElems, Size - Part * PartNumElems);
96}
97
98#if !defined(NDEBUG)
99std::string shortBundleName(ArrayRef<Value *> VL, int Idx) {
100 std::string Result;
101 raw_string_ostream OS(Result);
102 if (Idx >= 0)
103 OS << "Idx: " << Idx << ", ";
104 OS << "n=" << VL.size() << " [" << *VL.front() << ", ..]";
105 return Result;
106}
107#endif
108
110 auto *It = find_if(VL, IsaPred<Instruction>);
111 if (It == VL.end())
112 return false;
115 return true;
116
117 BasicBlock *BB = I0->getParent();
118 for (Value *V : iterator_range(It, VL.end())) {
119 if (isa<PoisonValue>(V))
120 continue;
121 auto *II = dyn_cast<Instruction>(V);
122 if (!II)
123 return false;
124
125 if (BB != II->getParent())
126 return false;
127 }
128 return true;
129}
130
132 // Constant expressions and globals can't be vectorized like normal integer/FP
133 // constants.
134 return all_of(VL, isConstant);
135}
136
138 Value *FirstNonUndef = nullptr;
139 for (Value *V : VL) {
140 if (isa<UndefValue>(V))
141 continue;
142 if (!FirstNonUndef) {
143 FirstNonUndef = V;
144 continue;
145 }
146 if (V != FirstNonUndef)
147 return false;
148 }
149 return FirstNonUndef != nullptr;
150}
151
153 if (LHS == RHS)
154 return RHS;
155 if ((LHS == Intrinsic::fma || LHS == Intrinsic::fmuladd) &&
156 (RHS == Intrinsic::fma || RHS == Intrinsic::fmuladd))
157 return Intrinsic::fma;
159}
160
161bool isCommutative(const Instruction *I, const Value *ValWithUses,
162 bool IsCopyable) {
163 if (auto *Cmp = dyn_cast<CmpInst>(I))
164 return Cmp->isCommutative();
165 if (auto *BO = dyn_cast<BinaryOperator>(I))
166 return BO->isCommutative() ||
167 (BO->getOpcode() == Instruction::Sub && ValWithUses->hasUseList() &&
168 !ValWithUses->hasNUsesOrMore(UsesLimit) &&
169 all_of(
170 ValWithUses->uses(),
171 [&](const Use &U) {
172 // Commutative, if icmp eq/ne sub, 0
173 CmpPredicate Pred;
174 if (match(U.getUser(),
175 m_ICmp(Pred, m_Specific(U.get()), m_Zero())) &&
176 (Pred == ICmpInst::ICMP_EQ || Pred == ICmpInst::ICMP_NE))
177 return true;
178 // Commutative, if abs(sub nsw, true) or abs(sub, false).
179 ConstantInt *Flag;
180 auto *I = dyn_cast<BinaryOperator>(U.get());
181 return match(U.getUser(),
182 m_Intrinsic<Intrinsic::abs>(
183 m_Specific(U.get()), m_ConstantInt(Flag))) &&
184 ((!IsCopyable && I && !I->hasNoSignedWrap()) ||
185 Flag->isOne());
186 })) ||
187 (BO->getOpcode() == Instruction::FSub && ValWithUses->hasUseList() &&
188 !ValWithUses->hasNUsesOrMore(UsesLimit) &&
189 all_of(ValWithUses->uses(), [](const Use &U) {
190 return match(U.getUser(),
191 m_Intrinsic<Intrinsic::fabs>(m_Specific(U.get())));
192 }));
193 return I->isCommutative();
194}
195
196bool isCommutative(const Instruction *I) { return isCommutative(I, I); }
197
198bool isCommutableOperand(const Instruction *I, Value *ValWithUses, unsigned Op,
199 bool IsCopyable) {
200 assert(isCommutative(I, ValWithUses, IsCopyable) &&
201 "The instruction is not commutative.");
202 if (isa<CmpInst>(I))
203 return true;
204 if (auto *BO = dyn_cast<BinaryOperator>(I)) {
205 switch (BO->getOpcode()) {
206 case Instruction::Sub:
207 case Instruction::FSub:
208 return true;
209 default:
210 break;
211 }
212 }
213 return I->isCommutableOperand(Op);
214}
215
218 // IntrinsicInst::isCommutative returns true if swapping the first "two"
219 // arguments to the intrinsic produces the same result.
220 constexpr unsigned IntrinsicNumOperands = 2;
221 return IntrinsicNumOperands;
222 }
223 return I->getNumOperands();
224}
225
226std::optional<unsigned> getElementIndex(const Value *Inst, unsigned Offset) {
227 if (auto Index = getInsertExtractIndex<InsertElementInst>(Inst, Offset))
228 return Index;
230 return Index;
231
232 unsigned Index = Offset;
233
234 const auto *IV = dyn_cast<InsertValueInst>(Inst);
235 if (!IV)
236 return std::nullopt;
237
238 Type *CurrentType = IV->getType();
239 for (unsigned I : IV->indices()) {
240 if (const auto *ST = dyn_cast<StructType>(CurrentType)) {
241 Index *= ST->getNumElements();
242 CurrentType = ST->getElementType(I);
243 } else if (const auto *AT = dyn_cast<ArrayType>(CurrentType)) {
244 Index *= AT->getNumElements();
245 CurrentType = AT->getElementType();
246 } else {
247 return std::nullopt;
248 }
249 Index += I;
250 }
251 return Index;
252}
253
255 auto *It = find_if(VL, IsaPred<Instruction>);
256 if (It == VL.end())
257 return true;
258 Instruction *MainOp = cast<Instruction>(*It);
259 unsigned Opcode = MainOp->getOpcode();
260 bool IsCmpOp = isa<CmpInst>(MainOp);
261 CmpInst::Predicate BasePred = IsCmpOp ? cast<CmpInst>(MainOp)->getPredicate()
263 return all_of(make_range(It, VL.end()), [&](Value *V) {
264 if (auto *CI = dyn_cast<CmpInst>(V))
265 return BasePred == CI->getPredicate();
266 if (auto *I = dyn_cast<Instruction>(V))
267 return I->getOpcode() == Opcode;
268 return isa<PoisonValue>(V);
269 });
270}
271
272std::optional<unsigned> getExtractIndex(const Instruction *E) {
273 unsigned Opcode = E->getOpcode();
274 assert((Opcode == Instruction::ExtractElement ||
275 Opcode == Instruction::ExtractValue) &&
276 "Expected extractelement or extractvalue instruction.");
277 if (Opcode == Instruction::ExtractElement) {
278 auto *CI = dyn_cast<ConstantInt>(E->getOperand(1));
279 if (!CI)
280 return std::nullopt;
281 // Check if the index is out of bound. We can get the source vector from
282 // operand 0.
283 unsigned Idx = CI->getZExtValue();
284 auto *EE = cast<ExtractElementInst>(E);
285 const unsigned VF = getNumElements(EE->getVectorOperandType());
286 if (Idx >= VF)
287 return std::nullopt;
288 return Idx;
289 }
290 auto *EI = cast<ExtractValueInst>(E);
291 if (EI->getNumIndices() != 1)
292 return std::nullopt;
293 return *EI->idx_begin();
294}
295
297 SmallVectorImpl<int> &Mask) {
298 Mask.clear();
299 const unsigned E = Indices.size();
300 Mask.resize(E, PoisonMaskElem);
301 for (unsigned I = 0; I < E; ++I)
302 Mask[Indices[I]] = I;
303}
304
306 assert(!Mask.empty() && "Expected non-empty mask.");
307 SmallVector<Value *> Prev(Scalars.size(),
308 PoisonValue::get(Scalars.front()->getType()));
309 Prev.swap(Scalars);
310 for (unsigned I = 0, E = Prev.size(); I < E; ++I)
311 if (Mask[I] != PoisonMaskElem)
312 Scalars[Mask[I]] = Prev[I];
313}
314
316 assert(!VL.empty() && "Expected non-empty list of values.");
317 Type *Ty = VL.consume_front()->getType();
318 return all_of(VL, [&](Value *V) { return V->getType() == Ty; });
319}
320
321template <typename T>
322std::optional<unsigned> getInsertExtractIndex(const Value *Inst,
323 unsigned Offset) {
324 static_assert(std::is_same_v<T, InsertElementInst> ||
325 std::is_same_v<T, ExtractElementInst>,
326 "unsupported T");
327 const auto *IE = dyn_cast<T>(Inst);
328 if (!IE)
329 return std::nullopt;
330 // InsertElement: result is the vector, index is op 2.
331 // ExtractElement: result is scalar, vector is op 0, index is op 1.
332 constexpr bool IsInsert = std::is_same_v<T, InsertElementInst>;
333 Type *VecTy = IsInsert ? IE->getType() : IE->getOperand(0)->getType();
334 const auto *VT = dyn_cast<FixedVectorType>(VecTy);
335 if (!VT)
336 return std::nullopt;
337 const auto *CI = dyn_cast<ConstantInt>(IE->getOperand(IsInsert ? 2 : 1));
338 if (!CI)
339 return std::nullopt;
340 if (CI->getValue().uge(VT->getNumElements()))
341 return std::nullopt;
342 unsigned Index = Offset;
343 Index *= VT->getNumElements();
344 Index += CI->getZExtValue();
345 return Index;
346}
347
348// Only these two specializations are used; instantiate them here so the
349// definition can stay out of the header.
350template std::optional<unsigned>
352template std::optional<unsigned>
354
356 auto *I = dyn_cast<Instruction>(V);
357 if (!I)
358 return true;
359 return !mayHaveNonDefUseDependency(*I) &&
360 all_of(I->operands(), [I](Value *V) {
361 auto *IO = dyn_cast<Instruction>(V);
362 if (!IO)
363 return true;
364 return isa<PHINode>(IO) || IO->getParent() != I->getParent();
365 });
366}
367
369 auto *I = dyn_cast<Instruction>(V);
370 if (!I)
371 return true;
372 // Limits the number of uses to save compile time.
373 return !I->mayReadOrWriteMemory() && !I->hasNUsesOrMore(UsesLimit) &&
374 all_of(I->users(), [I](User *U) {
375 auto *IU = dyn_cast<Instruction>(U);
376 if (!IU)
377 return true;
378 return IU->getParent() != I->getParent() || isa<PHINode>(IU);
379 });
380}
381
385
390
391void transformScalarShuffleIndiciesToVector(unsigned VecTyNumElements,
392 SmallVectorImpl<int> &Mask) {
393 // The ShuffleBuilder implementation use shufflevector to splat an "element".
394 // But the element have different meaning for SLP (scalar) and REVEC
395 // (vector). We need to expand Mask into masks which shufflevector can use
396 // directly.
397 SmallVector<int> NewMask(Mask.size() * VecTyNumElements);
398 for (unsigned I : seq<unsigned>(Mask.size()))
399 for (auto [J, MaskV] : enumerate(MutableArrayRef(NewMask).slice(
400 I * VecTyNumElements, VecTyNumElements)))
401 MaskV = Mask[I] == PoisonMaskElem ? PoisonMaskElem
402 : Mask[I] * VecTyNumElements + J;
403 Mask.swap(NewMask);
404}
405
407 if (VL.empty())
408 return 0;
410 return 0;
411 auto *SV = cast<ShuffleVectorInst>(VL.front());
412 unsigned SVNumElements =
413 cast<FixedVectorType>(SV->getOperand(0)->getType())->getNumElements();
414 unsigned ShuffleMaskSize = SV->getShuffleMask().size();
415 if (SVNumElements % ShuffleMaskSize != 0)
416 return 0;
417 unsigned GroupSize = SVNumElements / ShuffleMaskSize;
418 if (GroupSize == 0 || (VL.size() % GroupSize) != 0)
419 return 0;
420 unsigned NumGroup = 0;
421 for (size_t I = 0, E = VL.size(); I != E; I += GroupSize) {
422 auto *SV = cast<ShuffleVectorInst>(VL[I]);
423 Value *Src = SV->getOperand(0);
424 ArrayRef<Value *> Group = VL.slice(I, GroupSize);
425 SmallBitVector ExpectedIndex(GroupSize);
426 if (!all_of(Group, [&](Value *V) {
427 auto *SV = cast<ShuffleVectorInst>(V);
428 // From the same source.
429 if (SV->getOperand(0) != Src)
430 return false;
431 int Index;
432 if (!SV->isExtractSubvectorMask(Index))
433 return false;
434 ExpectedIndex.set(Index / ShuffleMaskSize);
435 return true;
436 }))
437 return 0;
438 if (!ExpectedIndex.all())
439 return 0;
440 ++NumGroup;
441 }
442 assert(NumGroup == (VL.size() / GroupSize) && "Unexpected number of groups");
443 return NumGroup;
444}
445
447 assert(getShufflevectorNumGroups(VL) && "Not supported shufflevector usage.");
448 auto *SV = cast<ShuffleVectorInst>(VL.front());
449 unsigned SVNumElements =
450 cast<FixedVectorType>(SV->getOperand(0)->getType())->getNumElements();
451 SmallVector<int> Mask;
452 unsigned AccumulateLength = 0;
453 for (Value *V : VL) {
454 auto *SV = cast<ShuffleVectorInst>(V);
455 for (int M : SV->getShuffleMask())
456 Mask.push_back(M == PoisonMaskElem ? PoisonMaskElem
457 : AccumulateLength + M);
458 AccumulateLength += SVNumElements;
459 }
460 return Mask;
461}
462
464 SmallBitVector UseMask(VF, true);
465 for (auto [Idx, Value] : enumerate(Mask)) {
466 if (Value == PoisonMaskElem) {
467 if (MaskArg == UseMask::UndefsAsMask)
468 UseMask.reset(Idx);
469 continue;
470 }
471 if (MaskArg == UseMask::FirstArg && Value < VF)
472 UseMask.reset(Value);
473 else if (MaskArg == UseMask::SecondArg && Value >= VF)
474 UseMask.reset(Value - VF);
475 }
476 return UseMask;
477}
478
479template <bool IsPoisonOnly>
481 SmallBitVector Res(UseMask.empty() ? 1 : UseMask.size(), true);
482 using T = std::conditional_t<IsPoisonOnly, PoisonValue, UndefValue>;
483 if (isa<T>(V))
484 return Res;
485 auto *VecTy = dyn_cast<FixedVectorType>(V->getType());
486 if (!VecTy)
487 return Res.reset();
488 auto *C = dyn_cast<Constant>(V);
489 if (!C) {
490 if (!UseMask.empty()) {
491 const Value *Base = V;
492 while (auto *II = dyn_cast<InsertElementInst>(Base)) {
493 Base = II->getOperand(0);
494 if (isa<T>(II->getOperand(1)))
495 continue;
496 std::optional<unsigned> Idx = getElementIndex(II);
497 if (!Idx) {
498 Res.reset();
499 return Res;
500 }
501 if (*Idx < UseMask.size() && !UseMask.test(*Idx))
502 Res.reset(*Idx);
503 }
504 // TODO: Add analysis for shuffles here too.
505 if (V == Base) {
506 Res.reset();
507 } else {
508 SmallBitVector SubMask(UseMask.size(), false);
509 Res &= isUndefVector<IsPoisonOnly>(Base, SubMask);
510 }
511 } else {
512 Res.reset();
513 }
514 return Res;
515 }
516 for (unsigned I = 0, E = VecTy->getNumElements(); I != E; ++I) {
517 if (Constant *Elem = C->getAggregateElement(I))
518 if (!isa<T>(Elem) &&
519 (UseMask.empty() || (I < UseMask.size() && !UseMask.test(I))))
520 Res.reset(I);
521 }
522 return Res;
523}
524
526 const SmallBitVector &);
528 const SmallBitVector &);
529
532 const TargetTransformInfo *TTI) {
533 if (!UserInst)
534 return false;
535 unsigned Opcode = UserInst->getOpcode();
536 switch (Opcode) {
537 case Instruction::Load: {
538 LoadInst *LI = cast<LoadInst>(UserInst);
539 return (LI->getPointerOperand() == Scalar);
540 }
541 case Instruction::Store: {
542 StoreInst *SI = cast<StoreInst>(UserInst);
543 return (SI->getPointerOperand() == Scalar);
544 }
545 case Instruction::Call: {
546 CallInst *CI = cast<CallInst>(UserInst);
548 return any_of(enumerate(CI->args()), [&](auto &&Arg) {
549 return isVectorIntrinsicWithScalarOpAtArg(ID, Arg.index(), TTI) &&
550 Arg.value().get() == Scalar;
551 });
552 }
553 default:
554 return false;
555 }
556}
557
565
567 if (LoadInst *LI = dyn_cast<LoadInst>(I))
568 return LI->isSimple();
570 return SI->isSimple();
572 return !MI->isVolatile();
573 return true;
574}
575
576bool isSelectedBaseLoad(Type *ScalarTy, ArrayRef<Value *> PointerOps,
577 const DataLayout &DL, Value *&TrueBase,
578 Value *&FalseBase,
579 SmallVectorImpl<Value *> &Conditions) {
580 TrueBase = nullptr;
581 FalseBase = nullptr;
582 uint64_t ScalarSize = DL.getTypeStoreSize(ScalarTy);
583 Conditions.assign(PointerOps.size(), nullptr);
584 for (auto [Idx, P] : enumerate(PointerOps)) {
585 Value *Base = P;
586 uint64_t Offset = 0;
587 if (auto *GEP = dyn_cast<GetElementPtrInst>(P)) {
588 APInt OffsetAP(DL.getIndexTypeSizeInBits(GEP->getType()), 0);
589 if (!GEP->accumulateConstantOffset(DL, OffsetAP) || OffsetAP.isNegative())
590 return false;
591 Offset = OffsetAP.getZExtValue();
592 Base = GEP->getPointerOperand();
593 }
594 auto *Sel = dyn_cast<SelectInst>(Base);
595 if (!Sel)
596 return false;
597 Value *T = Sel->getTrueValue();
598 Value *F = Sel->getFalseValue();
599 if (!TrueBase) {
600 if (T == F)
601 return false;
602 TrueBase = T;
603 FalseBase = F;
604 } else if (TrueBase != T || FalseBase != F) {
605 return false;
606 }
607 // Lane Idx must be at exactly Base + Idx * sizeof(ScalarTy); codegen reads
608 // contiguously from TrueBase/FalseBase starting at lane 0.
609 if (Offset != static_cast<uint64_t>(Idx) * ScalarSize)
610 return false;
611 Conditions[Idx] = Sel->getCondition();
612 }
613 return TrueBase != nullptr;
614}
615
617 bool ExtendingManyInputs) {
618 if (SubMask.empty())
619 return;
620 assert(
621 (!ExtendingManyInputs || SubMask.size() > Mask.size() ||
622 // Check if input scalars were extended to match the size of other node.
623 (SubMask.size() == Mask.size() && Mask.back() == PoisonMaskElem)) &&
624 "SubMask with many inputs support must be larger than the mask.");
625 if (Mask.empty()) {
626 Mask.append(SubMask.begin(), SubMask.end());
627 return;
628 }
629 SmallVector<int> NewMask(SubMask.size(), PoisonMaskElem);
630 int TermValue = std::min(Mask.size(), SubMask.size());
631 for (int I = 0, E = SubMask.size(); I < E; ++I) {
632 if (SubMask[I] == PoisonMaskElem ||
633 (!ExtendingManyInputs &&
634 (SubMask[I] >= TermValue || Mask[SubMask[I]] >= TermValue)))
635 continue;
636 NewMask[I] = Mask[SubMask[I]];
637 }
638 Mask.swap(NewMask);
639}
640
642 const size_t Sz = Order.size();
643 SmallBitVector UnusedIndices(Sz, /*t=*/true);
644 SmallBitVector MaskedIndices(Sz);
645 for (unsigned I = 0; I < Sz; ++I) {
646 if (Order[I] < Sz)
647 UnusedIndices.reset(Order[I]);
648 else
649 MaskedIndices.set(I);
650 }
651 if (MaskedIndices.none())
652 return;
653 assert(UnusedIndices.count() == MaskedIndices.count() &&
654 "Non-synced masked/available indices.");
655 int Idx = UnusedIndices.find_first();
656 int MIdx = MaskedIndices.find_first();
657 while (MIdx >= 0) {
658 assert(Idx >= 0 && "Indices must be synced.");
659 Order[MIdx] = Idx;
660 Idx = UnusedIndices.find_next(Idx);
661 MIdx = MaskedIndices.find_next(MIdx);
662 }
663}
664
666 unsigned Opcode0, unsigned Opcode1) {
667 unsigned ScalarTyNumElements = getNumElements(ScalarTy);
668 SmallBitVector OpcodeMask(VL.size() * ScalarTyNumElements, false);
669 for (unsigned Lane : seq<unsigned>(VL.size())) {
670 if (isa<PoisonValue>(VL[Lane]))
671 continue;
672 if (cast<Instruction>(VL[Lane])->getOpcode() == Opcode1)
673 OpcodeMask.set(Lane * ScalarTyNumElements,
674 Lane * ScalarTyNumElements + ScalarTyNumElements);
675 }
676 return OpcodeMask;
677}
678
680 assert(none_of(Val, [](Constant *C) { return C->getType()->isVectorTy(); }) &&
681 "Expected scalar constants.");
682 SmallVector<Constant *> NewVal(Val.size() * VF);
683 for (auto [I, V] : enumerate(Val))
684 std::fill_n(NewVal.begin() + I * VF, VF, V);
685 return NewVal;
686}
687
689 switch (Opcode) {
690 case Instruction::UDiv:
691 return Intrinsic::masked_udiv;
692 case Instruction::SDiv:
693 return Intrinsic::masked_sdiv;
694 case Instruction::URem:
695 return Intrinsic::masked_urem;
696 case Instruction::SRem:
697 return Intrinsic::masked_srem;
698 default:
699 llvm_unreachable("Unexpected opcode");
700 }
701}
702
703/// Returns true if \p I is a part of a single-use chain, computing an address,
704/// which does not pay off the vectorization: a constant table is accessed by a
705/// gather, while the indices, unrelated between the lanes, require a full
706/// buildvector, unlike the ones, shifted by a constant from a common base.
707static bool isNonProfitableIndex(const Instruction *I) {
708 constexpr unsigned MaxIndexChainLength = 3;
709 // A constant shift of a common base is a cheap buildvector, while the loads
710 // are vectorized together with the indices, computed from them.
711 auto IsProfitableOperand = [](const Value *V) {
712 if (isa<Constant>(V))
713 return true;
714 if (const auto *Cast = dyn_cast<CastInst>(V); Cast && Cast->hasOneUse())
715 V = Cast->getOperand(0);
716 return isa<LoadInst>(V);
717 };
718 const User *U = I->user_back();
719 for ([[maybe_unused]] unsigned _ : seq<unsigned>(MaxIndexChainLength)) {
720 if (const auto *GEP = dyn_cast<GetElementPtrInst>(U))
721 return isa<Constant>(GEP->getPointerOperand()) ||
722 none_of(I->operand_values(), IsProfitableOperand);
723 if (!isa<Instruction>(U) || !U->hasOneUse())
724 return false;
725 U = U->user_back();
726 }
727 return false;
728}
729
731 if (!I->hasOneUse() || isNonProfitableIndex(I))
732 return false;
733 // The operation with the identity or the absorbing constant is folded away
734 // before the codegen, the vector node only repacks the lanes.
735 if (const auto *BO = dyn_cast<BinaryOperator>(I)) {
736 unsigned Opcode = BO->getOpcode();
737 Type *Ty = BO->getType();
738 for (unsigned Idx : seq<unsigned>(2)) {
739 const auto *C = dyn_cast<Constant>(BO->getOperand(Idx));
741 Opcode, Ty, /*AllowRHSConstant=*/Idx == 1) ||
743 Opcode, Ty, /*AllowLHSConstant=*/Idx == 0)))
744 return false;
745 }
746 }
747 const User *U = I->user_back();
750 if (isa<CastInst>(I))
752 (!isa<CastInst>(U) || U->hasOneUse());
754 I);
755}
756
757Instruction *lookThroughCastRoundTrip(Value *V, bool MustBeElidable) {
758 auto *Wide = dyn_cast<FPExtInst>(V);
759 if (!Wide || !Wide->hasOneUse())
760 return nullptr;
761 auto *Narrow = dyn_cast<FPTruncInst>(Wide->getOperand(0));
762 if (!Narrow || !Narrow->hasOneUse())
763 return nullptr;
764 Value *Src = Narrow->getOperand(0);
765 if (!isa<Instruction>(Src) || Src->getType() != Wide->getType())
766 return nullptr;
767 if (MustBeElidable && !(Wide->hasAllowContract() && Wide->hasNoNaNs() &&
768 Wide->hasNoInfs() && Narrow->hasAllowContract()))
769 return nullptr;
770 return Narrow;
771}
772
773} // namespace llvm::slpvectorizer
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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
#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
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1565
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:330
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)
void swap(SmallVectorImpl &RHS)
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.
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.
A private "module" namespace for types and utilities used by this pass.
std::optional< unsigned > getExtractIndex(const Instruction *E)
Definition SLPUtils.cpp:272
template SmallBitVector isUndefVector< true >(const Value *, const SmallBitVector &)
bool areAllOperandsNonInsts(Value *V)
Checks if the provided value does not require scheduling.
Definition SLPUtils.cpp:355
std::optional< unsigned > getElementIndex(const Value *Inst, unsigned Offset)
Definition SLPUtils.cpp:226
bool doesInTreeUserNeedToExtract(Value *Scalar, Instruction *UserInst, TargetLibraryInfo *TLI, const TargetTransformInfo *TTI)
Definition SLPUtils.cpp:530
MemoryLocation getLocation(Instruction *I)
Definition SLPUtils.cpp:558
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:576
SmallBitVector getAltInstrMask(ArrayRef< Value * > VL, Type *ScalarTy, unsigned Opcode0, unsigned Opcode1)
Definition SLPUtils.cpp:665
SmallBitVector isUndefVector(const Value *V, const SmallBitVector &UseMask)
Checks if the given value is actually an undefined constant vector.
Definition SLPUtils.cpp:480
Intrinsic::ID getMaskedDivRemIntrinsic(unsigned Opcode)
Definition SLPUtils.cpp:688
bool isUsedOutsideBlock(Value *V)
Checks if the provided value does not require scheduling.
Definition SLPUtils.cpp:368
bool doesNotNeedToSchedule(ArrayRef< Value * > VL)
Checks if the specified array of instructions does not require scheduling.
Definition SLPUtils.cpp:386
std::optional< unsigned > getInsertExtractIndex(const Value *Inst, unsigned Offset)
Definition SLPUtils.cpp:322
void reorderScalars(SmallVectorImpl< Value * > &Scalars, ArrayRef< int > Mask)
Reorders the list of scalars in accordance with the given Mask.
Definition SLPUtils.cpp:305
bool allSameType(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:315
bool allSameOpcode(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:254
bool isSplat(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:137
unsigned getNumElements(Type *Ty)
Definition SLPUtils.cpp:82
std::string shortBundleName(ArrayRef< Value * > VL, int Idx)
Print a short descriptor of the instruction bundle suitable for debug output.
Definition SLPUtils.cpp:99
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:730
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:90
bool isCommutableOperand(const Instruction *I, Value *ValWithUses, unsigned Op, bool IsCopyable)
Checks if the operand is commutative.
Definition SLPUtils.cpp:198
void transformScalarShuffleIndiciesToVector(unsigned VecTyNumElements, SmallVectorImpl< int > &Mask)
Definition SLPUtils.cpp:391
SmallVector< int > calculateShufflevectorMask(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:446
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:463
bool isCommutative(const Instruction *I, const Value *ValWithUses, bool IsCopyable)
Definition SLPUtils.cpp:161
template SmallBitVector isUndefVector< false >(const Value *, const SmallBitVector &)
unsigned getNumberOfPotentiallyCommutativeOps(Instruction *I)
Definition SLPUtils.cpp:216
bool allConstant(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:131
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:296
bool allSameBlock(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:109
bool isReassocChainLink(const Instruction *I)
Definition SLPUtils.cpp:54
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:152
UseMask
Specifies the way the mask should be analyzed for undefs/poisonous elements in the shuffle mask.
Definition SLPUtils.h:240
@ SecondArg
The mask is expected to be for permutation of 2 vectors, check for the mask elements for the second a...
Definition SLPUtils.h:244
@ UndefsAsMask
Consider undef mask elements (-1) as placeholders for future shuffle elements and mark them as ones a...
Definition SLPUtils.h:247
@ FirstArg
The mask is expected to be for permutation of 1-2 vectors, check for the mask elements for the first ...
Definition SLPUtils.h:241
void addMask(SmallVectorImpl< int > &Mask, ArrayRef< int > SubMask, bool ExtendingManyInputs)
Shuffles Mask in accordance with the given SubMask.
Definition SLPUtils.cpp:616
bool isSimple(Instruction *I)
Definition SLPUtils.cpp:566
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:757
bool isBinOpIdentityConstant(const Value *V, unsigned Opcode)
Definition SLPUtils.cpp:38
unsigned getShufflevectorNumGroups(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:406
SmallVector< Constant * > replicateMask(ArrayRef< Constant * > Val, unsigned VF)
Replicates the given Val VF times.
Definition SLPUtils.cpp:679
unsigned getReassocCombineOpcode(unsigned Opcode)
Definition SLPUtils.cpp:43
bool isVectorLikeInstWithConstOps(Value *V)
Checks if V is one of vector-like instructions, i.e.
Definition SLPUtils.cpp:62
bool doesNotNeedToBeScheduled(Value *V)
Checks if the specified value does not require scheduling.
Definition SLPUtils.cpp:382
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:94
constexpr int UsesLimit
Limit of the number of uses for potentially transformed instructions/values, used in checks to avoid ...
Definition SLPUtils.h:42
bool isConstant(Value *V)
Definition SLPUtils.cpp:34
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:707
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:641
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