14#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64PERFECTSHUFFLE_H
15#define LLVM_LIB_TARGET_AARCH64_AARCH64PERFECTSHUFFLE_H
26 assert(M.size() == 4 &&
"Expected a 4 entry perfect shuffle");
30 return E.value() < 0 ||
E.value() == (int)
E.index();
34 return E.value() < 0 ||
E.value() == (int)
E.index() + 4;
40 unsigned PFIndexes[4];
41 for (
unsigned i = 0; i != 4; ++i) {
42 assert(M[i] < 8 &&
"Expected a maximum entry of 8 for shuffle mask");
50 unsigned PFTableIndex = PFIndexes[0] * 9 * 9 * 9 + PFIndexes[1] * 9 * 9 +
51 PFIndexes[2] * 9 + PFIndexes[3];
54 return (PFEntry >> 30) + 1;
63 unsigned &WhichResultOut,
unsigned &OperandOrderOut) {
70 bool Result0Order0 =
true;
71 bool Result1Order0 =
true;
72 bool Result0Order1 =
true;
73 bool Result1Order1 =
true;
75 for (
unsigned i = 0; i != NumElts; i += 2) {
79 Result0Order0 =
false;
80 if (EvenElt != NumElts / 2 + i / 2)
81 Result1Order0 =
false;
82 if (EvenElt != NumElts + i / 2)
83 Result0Order1 =
false;
84 if (EvenElt != NumElts + NumElts / 2 + i / 2)
85 Result1Order1 =
false;
88 unsigned OddElt = (
unsigned)M[i + 1];
89 if (OddElt != NumElts + i / 2)
90 Result0Order0 =
false;
91 if (OddElt != NumElts + NumElts / 2 + i / 2)
92 Result1Order0 =
false;
94 Result0Order1 =
false;
95 if (OddElt != NumElts / 2 + i / 2)
96 Result1Order1 =
false;
100 if (Result0Order0 + Result1Order0 + Result0Order1 + Result1Order1 != 1)
103 WhichResultOut = (Result0Order0 || Result0Order1) ? 0 : 1;
104 OperandOrderOut = (Result0Order0 || Result1Order0) ? 0 : 1;
112 unsigned &WhichResult) {
113 if (NumElts % 2 != 0)
115 WhichResult = (M[0] == 0 ? 0 : 1);
116 unsigned Idx = WhichResult * NumElts / 2;
117 for (
unsigned i = 0; i != NumElts; i += 2) {
118 if ((M[i] >= 0 && (
unsigned)M[i] != Idx) ||
119 (M[i + 1] >= 0 && (
unsigned)M[i + 1] != Idx))
131 unsigned &WhichResultOut) {
133 unsigned WhichResult = 2;
134 for (
unsigned i = 0; i != NumElts; i++) {
136 WhichResult = ((
unsigned)M[i] == i * 2 ? 0 : 1);
140 if (WhichResult == 2)
144 for (
unsigned i = 0; i != NumElts; ++i) {
147 if ((
unsigned)M[i] != 2 * i + WhichResult)
150 WhichResultOut = WhichResult;
158 unsigned &WhichResult) {
159 unsigned Half = NumElts / 2;
160 WhichResult = (M[0] == 0 ? 0 : 1);
161 for (
unsigned j = 0; j != 2; ++j) {
162 unsigned Idx = WhichResult;
163 for (
unsigned i = 0; i != Half; ++i) {
164 int MIdx = M[i + j * Half];
165 if (MIdx >= 0 && (
unsigned)MIdx != Idx)
180 unsigned &WhichResultOut,
unsigned &OperandOrderOut) {
181 if (NumElts % 2 != 0)
187 bool Result0Order0 =
true;
188 bool Result1Order0 =
true;
189 bool Result0Order1 =
true;
190 bool Result1Order1 =
true;
192 for (
unsigned i = 0; i != NumElts; i += 2) {
196 Result0Order0 =
false;
197 if (EvenElt != i + 1)
198 Result1Order0 =
false;
199 if (EvenElt != NumElts + i)
200 Result0Order1 =
false;
201 if (EvenElt != NumElts + i + 1)
202 Result1Order1 =
false;
205 unsigned OddElt = (
unsigned)M[i + 1];
206 if (OddElt != NumElts + i)
207 Result0Order0 =
false;
208 if (OddElt != NumElts + i + 1)
209 Result1Order0 =
false;
211 Result0Order1 =
false;
213 Result1Order1 =
false;
217 if (Result0Order0 + Result1Order0 + Result0Order1 + Result1Order1 != 1)
220 WhichResultOut = (Result0Order0 || Result0Order1) ? 0 : 1;
221 OperandOrderOut = (Result0Order0 || Result1Order0) ? 0 : 1;
229 unsigned &WhichResult) {
230 if (NumElts % 2 != 0)
232 WhichResult = (M[0] == 0 ? 0 : 1);
233 for (
unsigned i = 0; i < NumElts; i += 2) {
234 if ((M[i] >= 0 && (
unsigned)M[i] != i + WhichResult) ||
235 (M[i + 1] >= 0 && (
unsigned)M[i + 1] != i + WhichResult))
248 "Only possible block sizes for REV are: 16, 32, 64, 128");
250 unsigned BlockElts = M[0] + 1;
258 for (
unsigned i = 0; i < NumElts; ++i) {
261 if ((
unsigned)M[i] != (i - i % BlockElts) + (BlockElts - 1 - i % BlockElts))
273 const int *FirstRealElt =
find_if(M, [](
int Elt) {
return Elt >= 0; });
274 if (FirstRealElt == M.end())
279 APInt ExpectedElt =
APInt(MaskBits, *FirstRealElt + 1,
false,
283 if (std::any_of(FirstRealElt + 1, M.end(),
284 [&](
int Elt) { return Elt != ExpectedElt++ && Elt >= 0; }))
323 unsigned ExpectedElt =
Imm;
324 for (
unsigned I = 1;
I < NumElts; ++
I) {
328 if (ExpectedElt == NumElts)
333 if (ExpectedElt !=
static_cast<unsigned>(M[
I]))
343 unsigned SegmentSize) {
347 if (SegmentSize * Segments != Mask.size())
351 if (Lane >= SegmentSize)
357 const unsigned SegmentIndex =
P.index() / SegmentSize;
358 return P.value() < 0 ||
359 unsigned(
P.value()) == Lane + SegmentIndex * SegmentSize;
368 unsigned SegmentSize) {
370 if (SegmentSize * Segments != Mask.size())
376 const unsigned IndexWithinSegment =
P.index() % SegmentSize;
377 return P.value() < 0 ||
unsigned(
P.value()) == IndexWithinSegment;
427 unsigned LHSID = (PFEntry >> 13) & ((1 << 13) - 1);
428 unsigned RHSID = (PFEntry >> 0) & ((1 << 13) - 1);
431 if (LHSID == (1 * 9 + 2) * 9 + 3)
433 assert(LHSID == ((4 * 9 + 5) * 9 + 6) * 9 + 7 &&
"Illegal OP_COPY!");
441 auto getPFIDLane = [](
unsigned ID,
int Elt) ->
int {
442 assert(Elt < 4 &&
"Expected Perfect Lanes to be less than 4");
448 return (ID % 9 == 8) ? -1 : ID % 9;
454 int MaskElt = getPFIDLane(PFTableIndex, (RHSID & 0x01) << 1) >> 1;
457 (getPFIDLane(PFTableIndex, ((RHSID & 0x01) << 1) + 1) - 1) >> 1;
458 assert(MaskElt >= 0 &&
"Didn't expect an undef movlane index!");
459 unsigned ExtLane = MaskElt < 2 ? MaskElt : (MaskElt - 2);
461 (MaskElt >= 2) << 16 | ExtLane << 8 | (RHSID & 0x3)});
463 int MaskElt = getPFIDLane(PFTableIndex, RHSID);
464 assert(MaskElt >= 0 &&
"Didn't expect an undef movlane index!");
465 unsigned ExtLane = MaskElt < 4 ? MaskElt : (MaskElt - 4);
467 (MaskElt >= 4) << 16 | ExtLane << 8 | (RHSID & 0x3)});
469 return Entries.
size() - 1;
474 Entries.
push_back({OpNum, OpLHS, OpRHS});
475 return Entries.
size() - 1;
483 assert(NumElts == 4 &&
"Only 4 element masks supported at the moment");
486 unsigned PFIndexes[4];
487 for (
unsigned i = 0; i != 4; ++i) {
491 PFIndexes[i] = Mask[i];
494 unsigned PFTableIndex = PFIndexes[0] * 9 * 9 * 9 + PFIndexes[1] * 9 * 9 +
495 PFIndexes[2] * 9 + PFIndexes[3];
497 return Idx == Entries.
size() - 1;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static const int BlockSize
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
unsigned logBase2() const
Represent a constant reference to an array (0 or more elements consecutively in memory),...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This is an optimization pass for GlobalISel generic memory operations.
std::optional< unsigned > isDUPQMask(ArrayRef< int > Mask, unsigned Segments, unsigned SegmentSize)
isDUPQMask - matches a splat of equivalent lanes within segments of a given number of elements.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool isZIPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for zip1 or zip2 masks of the form: <0, 8, 1, 9, 2, 10, 3, 11> (WhichResultOut = 0,...
bool isEXTMask(ArrayRef< int > M, unsigned NumElts, bool &ReverseEXT, unsigned &Imm)
Check if an EXT instruction can handle the shuffle mask when the vector sources of the shuffle are di...
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
bool isDUPFirstSegmentMask(ArrayRef< int > Mask, unsigned Segments, unsigned SegmentSize)
isDUPFirstSegmentMask - matches a splat of the first 128b segment.
unsigned generatePerfectShuffleFromTable(unsigned PFTableIndex, SmallVector< ShuffleEntry > &Entries)
bool generatePerfectShuffle(ArrayRef< int > Mask, unsigned NumElts, SmallVector< ShuffleEntry > &Entries)
generatePerfectShuffle - Given a Mask, attempt to generate the optimal sequence of instructions using...
unsigned getPerfectShuffleCost(llvm::ArrayRef< int > M)
bool isSingletonEXTMask(ArrayRef< int > M, unsigned NumElts, unsigned &Imm)
check if an EXT instruction can handle the shuffle mask when the vector sources of the shuffle are th...
bool isUZPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut)
Return true for uzp1 or uzp2 masks of the form: <0, 2, 4, 6, 8, 10, 12, 14> or <1,...
bool isREVMask(ArrayRef< int > M, unsigned EltSize, unsigned NumElts, unsigned BlockSize)
isREVMask - Check if a vector shuffle corresponds to a REV instruction with the specified blocksize.
bool isUZP_v_undef_Mask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResult)
isUZP_v_undef_Mask - Special case of isUZPMask for canonical form of "vector_shuffle v,...
const unsigned PerfectShuffleTable[6561+1]
bool isZIP_v_undef_Mask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResult)
isZIP_v_undef_Mask - Special case of isZIPMask for canonical form of "vector_shuffle v,...
bool isTRN_v_undef_Mask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResult)
isTRN_v_undef_Mask - Special case of isTRNMask for canonical form of "vector_shuffle v,...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
bool isTRNMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for trn1 or trn2 masks of the form: <0, 8, 2, 10, 4, 12, 6, 14> (WhichResultOut = 0,...
ShuffleEntry - Represent a shuffle entry in the decomposion of a vector shuffle.
IDs
Special IDs for the LHS and RHS values.