LLVM: include/llvm/Analysis/VectorUtils.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef LLVM_ANALYSIS_VECTORUTILS_H
14#define LLVM_ANALYSIS_VECTORUTILS_H
15
24
25namespace llvm {
28
29
30
31
32
34
36
38
39
41
42
43
44 static void getVFABIMappings(const CallInst &CI,
46 if (!CI.getCalledFunction())
47 return;
48
49 const StringRef ScalarName = CI.getCalledFunction()->getName();
50
52
53
55 if (ListOfStrings.empty())
56 return;
57 for (const auto &MangledName : ListOfStrings) {
58 const std::optional Shape =
60
61
62
63
64 if (Shape && (Shape->ScalarName == ScalarName)) {
65 assert(CI.getModule()->getFunction(Shape->VectorName) &&
66 "Vector function is missing.");
68 }
69 }
70 }
71
72public:
73
76
77
78 getVFABIMappings(CI, Ret);
79
80
81
82 return Ret;
83 }
84
86 std::optional VF = std::nullopt) {
87
88
89
92 if (!VF || Info.Shape.VF == *VF)
93 if (Info.isMasked())
94 return true;
95
96 return false;
97 }
98
99
101 : M(CI.getModule()), CI(CI),
103
104
105
106
107
110 return CI.getCalledFunction();
111
112 for (const auto &Info : ScalarToVectorMappings)
113 if (Info.Shape == Shape)
115
116 return nullptr;
117 }
118
119};
120
121template class ArrayRef;
122class DemandedBits;
123template class InterleaveGroup;
124class IRBuilderBase;
125class Loop;
126class TargetTransformInfo;
127class Value;
128
129namespace Intrinsic {
130typedef unsigned ID;
131}
132
133
134
135
136
137
138
140
141
142
143
144
145
146
147
148
151
152
153
154
158
159
160
161
162
166
167
168
169
170
173
174
175
176
179
180
182
183
185
186
187
189
190
191
192
194
195
196
197
199
200
201
202
204
205
206
207
208
209
210
212
213
214
215
216
218 const APInt &DemandedElts,
219 APInt &DemandedLHS, APInt &DemandedRHS,
220 bool AllowUndefElts = false);
221
222
223
224
225
226
227
229 std::array<std::pair<int, int>, 2> &SrcInfo);
230
231
232
233
234
235
236
237
238
239
240
241
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
262
263
264
265
266
269
270
271
272
273
274
277
278
279
282
283
284
285
286
287
288
289
290
291
292
293
294
296 ArrayRef Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs,
297 unsigned NumOfUsedRegs, function_ref<void()> NoInputAction,
300 ManyInputsAction);
301
302
303
304
305
306
307
308
309
310
311
312
313
315 const APInt &DemandedElts,
316 APInt &DemandedLHS,
317 APInt &DemandedRHS);
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
356
357
358
359
360
362
363
364
365
366
367
368
371
372
373
374
375
379
380
381
382
383
384
385
386
387
389
390
391
392
393
394
395
396
397
398
399
400
404
405
406
407
408
409
410
411
412
413
414
415
416
419
420
421
422
423
424
425
426
427
428
429
430
432 unsigned NumVecs);
433
434
435
436
437
438
439
440
441
442
443
444
445
447createStrideMask(unsigned Start, unsigned Stride, unsigned VF);
448
449
450
451
452
453
454
455
456
457
458
459
462
463
464
465
467 unsigned NumElts);
468
469
470
471
472
473
474
475
478
479
480
481
483
484
485
486
488
489
490
491
493
494
495
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
525public:
527 : Factor(Factor), Reverse(Reverse), Alignment(Alignment),
528 InsertPos(nullptr) {}
529
531 : Alignment(Alignment), InsertPos(Instr) {
532 Factor = std::abs(Stride);
533 assert(Factor > 1 && "Invalid interleave factor");
534
535 Reverse = Stride < 0;
536 Members[0] = Instr;
537 }
538
543
544
545
546
547
548
550
551 std::optional<int32_t> MaybeKey = checkedAdd(Index, SmallestKey);
552 if (!MaybeKey)
553 return false;
554 int32_t Key = *MaybeKey;
555
556
559 return false;
560
561
562 if (Members.contains(Key))
563 return false;
564
565 if (Key > LargestKey) {
566
567 if (Index >= static_cast<int32_t>(Factor))
568 return false;
569
570 LargestKey = Key;
571 } else if (Key < SmallestKey) {
572
573
574 std::optional<int32_t> MaybeLargestIndex = checkedSub(LargestKey, Key);
575 if (!MaybeLargestIndex)
576 return false;
577
578
579 if (*MaybeLargestIndex >= static_cast<int64_t>(Factor))
580 return false;
581
582 SmallestKey = Key;
583 }
584
585
586 Alignment = std::min(Alignment, NewAlign);
587 Members[Key] = Instr;
588 return true;
589 }
590
591
592
593
595 int32_t Key = SmallestKey + Index;
596 return Members.lookup(Key);
597 }
598
599
600
602 for (auto I : Members) {
603 if (I.second == Instr)
604 return I.first - SmallestKey;
605 }
606
608 }
609
612
613
614
615
616
617
618
620
621
623
624
626 return false;
627
628
629
630 assert(() && "Group should have been invalidated");
631
632
633 return true;
634 }
635
636
638
639private:
640 uint32_t Factor;
644 int32_t SmallestKey = 0;
645 int32_t LargestKey = 0;
646
647
648
649
650
651
652
653
654
655
656
657
658 InstTy *InsertPos;
659};
660
661
662
663
664
665
666
667
668
670public:
674 : PSE(PSE), TheLoop(L), DT(DT), LI(LI), LAI(LAI) {}
675
677
678
679
680
681
683
684
685
686
687
688
690 if (InterleaveGroups.empty()) {
692 !RequiresScalarEpilogue &&
693 "RequiresScalarEpilog should not be set without interleave groups");
694 return false;
695 }
696
697 InterleaveGroupMap.clear();
698 for (auto *Ptr : InterleaveGroups)
699 delete Ptr;
700 InterleaveGroups.clear();
701 RequiresScalarEpilogue = false;
702 return true;
703 }
704
705
707 return InterleaveGroupMap.contains(Instr);
708 }
709
710
711
712
715 return InterleaveGroupMap.lookup(Instr);
716 }
717
720 return make_range(InterleaveGroups.begin(), InterleaveGroups.end());
721 }
722
723
724
726
727
728
729
731
732
733 bool hasGroups() const { return !InterleaveGroups.empty(); }
734
735private:
736
737
738
739
741
742 Loop *TheLoop;
746
747
748
749
750 bool RequiresScalarEpilogue = false;
751
752
754
756
757
758
760
761
762 struct StrideDescriptor {
763 StrideDescriptor() = default;
764 StrideDescriptor(int64_t Stride, const SCEV *Scev, uint64_t Size,
766 : Stride(Stride), Scev(Scev), Size(Size), Alignment(Alignment) {}
767
768
769 int64_t Stride = 0;
770
771
772 const SCEV *Scev = nullptr;
773
774
776
777
778 Align Alignment;
779 };
780
781
782 using StrideEntry = std::pair<Instruction *, StrideDescriptor>;
783
784
785
786
787
788 InterleaveGroup *
789 createInterleaveGroup(Instruction *Instr, int Stride, Align Alignment) {
790 auto [It, Inserted] = InterleaveGroupMap.try_emplace(Instr);
791 assert(Inserted && "Already in an interleaved access group");
792 It->second = new InterleaveGroup(Instr, Stride, Alignment);
793 InterleaveGroups.insert(It->second);
794 return It->second;
795 }
796
797
798 void releaseGroup(InterleaveGroup *Group) {
799 InterleaveGroups.erase(Group);
800 releaseGroupWithoutRemovingFromSet(Group);
801 }
802
803
804
805 void releaseGroupWithoutRemovingFromSet(InterleaveGroup *Group) {
806 for (unsigned i = 0; i < Group->getFactor(); i++)
807 if (Instruction *Member = Group->getMember(i))
808 InterleaveGroupMap.erase(Member);
809
810 delete Group;
811 }
812
813
814 void collectConstStrideAccesses(
815 MapVector<Instruction *, StrideDescriptor> &AccessStrideInfo,
816 const DenseMap<Value *, const SCEV *> &Strides);
817
818
819 LLVM_ABI static bool isStrided(int Stride);
820
821
822 bool isPredicated(BasicBlock *BB) const {
824 }
825
826
827 bool areDependencesValid() const {
828 return LAI && LAI->getDepChecker().getDependences();
829 }
830
831
832
833
834
835
836 bool canReorderMemAccessesForInterleavedGroups(StrideEntry *A,
837 StrideEntry *B) const {
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853 auto *Src = A->first;
854 auto SrcDes = A->second;
855
856
858 auto SinkDes = B->second;
859
860
861
862 if (!Src->mayWriteToMemory())
863 return true;
864
865
866 if (!isStrided(SrcDes.Stride) && !isStrided(SinkDes.Stride))
867 return true;
868
869
870
871 if (!areDependencesValid())
872 return false;
873
874
875
876 return !Dependences.contains(Src) || !Dependences.lookup(Src).count(Sink);
877 }
878
879
880
881
882
883 void collectDependences() {
884 if (!areDependencesValid())
885 return;
886 const auto &DepChecker = LAI->getDepChecker();
887 auto *Deps = DepChecker.getDependences();
888 for (auto Dep : *Deps)
889 Dependences[Dep.getSource(DepChecker)].insert(
890 Dep.getDestination(DepChecker));
891 }
892};
893
894}
895
896#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Module.h This file contains the declarations for the Module class.
This file implements a map that provides insertion order iteration.
This file defines the SmallVector class.
Class for arbitrary precision integers.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
This class represents a function call, abstracting a target machine's calling convention.
This is an important base class in LLVM.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
const Function & getFunction() const
Common base class shared among various IRBuilders.
The group of interleaved loads/stores sharing the same stride and close to each other.
Definition VectorUtils.h:524
bool requiresScalarEpilogue() const
Returns true if this Group requires a scalar iteration to handle gaps.
Definition VectorUtils.h:622
uint32_t getFactor() const
Definition VectorUtils.h:540
InstTy * getMember(uint32_t Index) const
Get the member with the given index Index.
Definition VectorUtils.h:594
InterleaveGroup(uint32_t Factor, bool Reverse, Align Alignment)
Definition VectorUtils.h:526
bool isFull() const
Return true if this group is full, i.e. it has no gaps.
Definition VectorUtils.h:637
uint32_t getIndex(const InstTy *Instr) const
Get the index for the given member.
Definition VectorUtils.h:601
void setInsertPos(InstTy *Inst)
Definition VectorUtils.h:611
bool isReverse() const
Definition VectorUtils.h:539
InstTy * getInsertPos() const
Definition VectorUtils.h:610
void addMetadata(InstTy *NewInst) const
Add metadata (e.g.
Align getAlign() const
Definition VectorUtils.h:541
InterleaveGroup(InstTy *Instr, int32_t Stride, Align Alignment)
Definition VectorUtils.h:530
bool insertMember(InstTy *Instr, int32_t Index, Align NewAlign)
Try to insert a new member Instr with index Index and alignment NewAlign.
Definition VectorUtils.h:549
uint32_t getNumMembers() const
Definition VectorUtils.h:542
InterleaveGroup< Instruction > * getInterleaveGroup(const Instruction *Instr) const
Get the interleave group that Instr belongs to.
Definition VectorUtils.h:714
bool requiresScalarEpilogue() const
Returns true if an interleaved group that may access memory out-of-bounds requires a scalar epilogue ...
Definition VectorUtils.h:725
bool hasGroups() const
Returns true if we have any interleave groups.
Definition VectorUtils.h:733
bool isInterleaved(Instruction *Instr) const
Check if Instr belongs to any interleave group.
Definition VectorUtils.h:706
bool invalidateGroups()
Invalidate groups, e.g., in case all blocks in loop will be predicated contrary to original assumptio...
Definition VectorUtils.h:689
iterator_range< SmallPtrSetIterator< llvm::InterleaveGroup< Instruction > * > > getInterleaveGroups()
Definition VectorUtils.h:719
LLVM_ABI void analyzeInterleaving(bool EnableMaskedInterleavedGroup)
Analyze the interleaved accesses and collect them in interleave groups.
LLVM_ABI void invalidateGroupsRequiringScalarEpilogue()
Invalidate groups that require a scalar epilogue (due to gaps).
~InterleavedAccessInfo()
Definition VectorUtils.h:676
InterleavedAccessInfo(PredicatedScalarEvolution &PSE, Loop *L, DominatorTree *DT, LoopInfo *LI, const LoopAccessInfo *LAI)
Definition VectorUtils.h:671
A wrapper class for inspecting calls to intrinsic functions.
Drive the analysis of memory accesses in the loop.
static LLVM_ABI bool blockNeedsPredication(const BasicBlock *BB, const Loop *TheLoop, const DominatorTree *DT)
Return true if the block BB needs to be predicated in order for the loop to be vectorized.
Represents a single loop in the control flow graph.
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
This class represents an analyzed expression in the program.
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 push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
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.
VFDatabase(CallInst &CI)
Constructor, requires a CallInst instance.
Definition VectorUtils.h:100
static bool hasMaskedVariant(const CallInst &CI, std::optional< ElementCount > VF=std::nullopt)
Definition VectorUtils.h:85
static SmallVector< VFInfo, 8 > getMappings(const CallInst &CI)
Retrieve all the VFInfo instances associated to the CallInst CI.
Definition VectorUtils.h:74
LLVM Value Representation.
Base class of all SIMD vector types.
An efficient, type-erasing, non-owning reference to a callable.
A range adaptor for a pair of iterators.
Function * getVectorizedFunction(const VFShape &Shape) const
Definition VectorUtils.h:108
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
LLVM_ABI std::optional< VFInfo > tryDemangleForVFABI(StringRef MangledName, const FunctionType *FTy)
Function to construct a VFInfo out of a mangled names in the following format:
LLVM_ABI void getVectorVariantNames(const CallInst &CI, SmallVectorImpl< std::string > &VariantMappings)
Populates a set of strings representing the Vector Function ABI variants associated to the CallInst C...
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool isTriviallyScalarizable(Intrinsic::ID ID, const TargetTransformInfo *TTI)
Identify if the intrinsic is trivially scalarizable.
LLVM_ABI Intrinsic::ID getVectorIntrinsicIDForCall(const CallInst *CI, const TargetLibraryInfo *TLI)
Returns intrinsic ID for call.
LLVM_ABI APInt possiblyDemandedEltsInMask(Value *Mask)
Given a mask vector of the form , return an APInt (of bitwidth Y) for each lane which may be ...
LLVM_ABI llvm::SmallVector< int, 16 > createUnaryMask(ArrayRef< int > Mask, unsigned NumElts)
Given a shuffle mask for a binary shuffle, create the equivalent shuffle mask assuming both operands ...
LLVM_ABI void getMetadataToPropagate(Instruction *Inst, SmallVectorImpl< std::pair< unsigned, MDNode * > > &Metadata)
Add metadata from Inst to Metadata, if it can be preserved after vectorization.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
LLVM_ABI Instruction * propagateMetadata(Instruction *I, ArrayRef< Value * > VL)
Specifically, let Kinds = [MD_tbaa, MD_alias_scope, MD_noalias, MD_fpmath, MD_nontemporal,...
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI MDNode * intersectAccessGroups(const Instruction *Inst1, const Instruction *Inst2)
Compute the access-group list of access groups that Inst1 and Inst2 are both in.
LLVM_ABI bool getShuffleDemandedElts(int SrcWidth, ArrayRef< int > Mask, const APInt &DemandedElts, APInt &DemandedLHS, APInt &DemandedRHS, bool AllowUndefElts=false)
Transform a shuffle mask's output demanded element mask into demanded element masks for the 2 operand...
LLVM_ABI bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)
Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...
LLVM_ABI Constant * createBitMaskForGaps(IRBuilderBase &Builder, unsigned VF, const InterleaveGroup< Instruction > &Group)
Create a mask that filters the members of an interleave group where there are gaps.
LLVM_ABI llvm::SmallVector< int, 16 > createStrideMask(unsigned Start, unsigned Stride, unsigned VF)
Create a stride shuffle mask.
LLVM_ABI void getHorizDemandedEltsForFirstOperand(unsigned VectorBitWidth, const APInt &DemandedElts, APInt &DemandedLHS, APInt &DemandedRHS)
Compute the demanded elements mask of horizontal binary operations.
LLVM_ABI llvm::SmallVector< int, 16 > createReplicatedMask(unsigned ReplicationFactor, unsigned VF)
Create a mask with replicated elements.
LLVM_ABI unsigned getDeinterleaveIntrinsicFactor(Intrinsic::ID ID)
Returns the corresponding factor of llvm.vector.deinterleaveN intrinsics.
LLVM_ABI unsigned getInterleaveIntrinsicFactor(Intrinsic::ID ID)
Returns the corresponding factor of llvm.vector.interleaveN intrinsics.
LLVM_ABI bool maskIsAllOneOrUndef(Value *Mask)
Given a mask vector of i1, Return true if all of the elements of this predicate mask are known to be ...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI bool isVectorIntrinsicWithStructReturnOverloadAtField(Intrinsic::ID ID, int RetIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic that returns a struct is overloaded at the struct elem...
LLVM_ABI void narrowShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Replace each shuffle mask index with the scaled sequential indices for an equivalent mask of narrowed...
LLVM_ABI bool isMaskedSlidePair(ArrayRef< int > Mask, int NumElts, std::array< std::pair< int, int >, 2 > &SrcInfo)
Does this shuffle mask represent either one slide shuffle or a pair of two slide shuffles,...
LLVM_ABI VectorType * getDeinterleavedVectorType(IntrinsicInst *DI)
Given a deinterleaveN intrinsic, return the (narrow) vector type of each factor.
LLVM_ABI llvm::SmallVector< int, 16 > createInterleaveMask(unsigned VF, unsigned NumVecs)
Create an interleave shuffle mask.
LLVM_ABI bool isVectorIntrinsicWithScalarOpAtArg(Intrinsic::ID ID, unsigned ScalarOpdIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic has a scalar operand.
LLVM_ABI Value * findScalarElement(Value *V, unsigned EltNo)
Given a vector and an element number, see if the scalar value is already around as a register,...
LLVM_ABI MDNode * uniteAccessGroups(MDNode *AccGroups1, MDNode *AccGroups2)
Compute the union of two access-group lists.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI bool maskIsAllZeroOrUndef(Value *Mask)
Given a mask vector of i1, Return true if all of the elements of this predicate mask are known to be ...
std::enable_if_t< std::is_signed_v< T >, std::optional< T > > checkedSub(T LHS, T RHS)
Subtract two signed integers LHS and RHS.
LLVM_ABI void getShuffleMaskWithWidestElts(ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Repetitively apply widenShuffleMaskElts() for as long as it succeeds, to get the shuffle mask with wi...
std::enable_if_t< std::is_signed_v< T >, std::optional< T > > checkedAdd(T LHS, T RHS)
Add two signed integers LHS and RHS.
LLVM_ABI void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
LLVM_ABI bool maskContainsAllOneOrUndef(Value *Mask)
Given a mask vector of i1, Return true if any of the elements of this predicate mask are known to be ...
LLVM_ABI bool isTriviallyVectorizable(Intrinsic::ID ID)
Identify if the intrinsic is trivially vectorizable.
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
LLVM_ABI bool isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID, int OpdIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic is overloaded on the type of the operand at index OpdI...
LLVM_ABI MapVector< Instruction *, uint64_t > computeMinimumValueSizes(ArrayRef< BasicBlock * > Blocks, DemandedBits &DB, const TargetTransformInfo *TTI=nullptr)
Compute a map of integer instructions to their minimum legal type size.
LLVM_ABI bool scaleShuffleMaskElts(unsigned NumDstElts, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Attempt to narrow/widen the Mask shuffle mask to the NumDstElts target width.
LLVM_ABI int getSplatIndex(ArrayRef< int > Mask)
If all non-negative Mask elements are the same value, return that value.
This struct is a compact representation of a valid (non-zero power of two) alignment.
An information struct used to provide DenseMap with the various necessary components for a given valu...
Holds the VFShape for a specific scalar to vector function mapping.
Contains the information about the kind of vectorization available.
static VFShape getScalarShape(const FunctionType *FTy)
Retrieve the VFShape that can be used to map a scalar function to itself, with VF = 1.