14#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64PERFECTSHUFFLE_H
15#define LLVM_LIB_TARGET_AARCH64_AARCH64PERFECTSHUFFLE_H
6593 assert(M.size() == 4 &&
"Expected a 4 entry perfect shuffle");
6597 return E.value() < 0 ||
E.value() == (int)
E.index();
6601 return E.value() < 0 ||
E.value() == (int)
E.index() + 4;
6607 unsigned PFIndexes[4];
6608 for (
unsigned i = 0; i != 4; ++i) {
6609 assert(M[i] < 8 &&
"Expected a maximum entry of 8 for shuffle mask");
6613 PFIndexes[i] = M[i];
6617 unsigned PFTableIndex = PFIndexes[0] * 9 * 9 * 9 + PFIndexes[1] * 9 * 9 +
6618 PFIndexes[2] * 9 + PFIndexes[3];
6621 return (PFEntry >> 30) + 1;
6630 unsigned &WhichResultOut,
unsigned &OperandOrderOut) {
6631 if (NumElts % 2 != 0)
6636 bool Variant0Order0 =
true;
6637 bool Variant1Order0 =
true;
6638 bool Variant0Order1 =
true;
6639 bool Variant1Order1 =
true;
6641 for (
unsigned i = 0; i != NumElts; i += 2) {
6644 if (EvenElt != i / 2)
6645 Variant0Order0 =
false;
6646 if (EvenElt != NumElts / 2 + i / 2)
6647 Variant1Order0 =
false;
6648 if (EvenElt != NumElts + i / 2)
6649 Variant0Order1 =
false;
6650 if (EvenElt != NumElts + NumElts / 2 + i / 2)
6651 Variant1Order1 =
false;
6653 if (M[i + 1] >= 0) {
6654 unsigned OddElt = (
unsigned)M[i + 1];
6655 if (OddElt != NumElts + i / 2)
6656 Variant0Order0 =
false;
6657 if (OddElt != NumElts + NumElts / 2 + i / 2)
6658 Variant1Order0 =
false;
6659 if (OddElt != i / 2)
6660 Variant0Order1 =
false;
6661 if (OddElt != NumElts / 2 + i / 2)
6662 Variant1Order1 =
false;
6666 if (Variant0Order0 + Variant1Order0 + Variant0Order1 + Variant1Order1 != 1)
6669 WhichResultOut = (Variant0Order0 || Variant0Order1) ? 0 : 1;
6670 OperandOrderOut = (Variant0Order0 || Variant1Order0) ? 0 : 1;
6678 unsigned &WhichResultOut) {
6680 unsigned WhichResult = 2;
6681 for (
unsigned i = 0; i != NumElts; i++) {
6683 WhichResult = ((
unsigned)M[i] == i * 2 ? 0 : 1);
6687 if (WhichResult == 2)
6691 for (
unsigned i = 0; i != NumElts; ++i) {
6694 if ((
unsigned)M[i] != 2 * i + WhichResult)
6697 WhichResultOut = WhichResult;
6705 unsigned &WhichResultOut) {
6706 if (NumElts % 2 != 0)
6709 unsigned WhichResult = 2;
6710 for (
unsigned i = 0; i != NumElts; i += 2) {
6712 WhichResult = ((
unsigned)M[i] == i ? 0 : 1);
6715 if (M[i + 1] >= 0) {
6716 WhichResult = ((
unsigned)M[i + 1] == i + NumElts ? 0 : 1);
6720 if (WhichResult == 2)
6723 for (
unsigned i = 0; i < NumElts; i += 2) {
6724 if ((M[i] >= 0 && (
unsigned)M[i] != i + WhichResult) ||
6725 (M[i + 1] >= 0 && (
unsigned)M[i + 1] != i + NumElts + WhichResult))
6728 WhichResultOut = WhichResult;
6739 "Only possible block sizes for REV are: 16, 32, 64, 128");
6741 unsigned BlockElts = M[0] + 1;
6749 for (
unsigned i = 0; i < NumElts; ++i) {
6752 if ((
unsigned)M[i] != (i - i % BlockElts) + (BlockElts - 1 - i % BlockElts))
6762 unsigned SegmentSize) {
6766 if (SegmentSize * Segments != Mask.size())
6767 return std::nullopt;
6770 if (Lane >= SegmentSize)
6771 return std::nullopt;
6776 const unsigned SegmentIndex =
P.index() / SegmentSize;
6777 return P.value() < 0 ||
6778 unsigned(
P.value()) == Lane + SegmentIndex * SegmentSize;
6782 return std::nullopt;
6787 unsigned SegmentSize) {
6789 if (SegmentSize * Segments != Mask.size())
6795 const unsigned IndexWithinSegment =
P.index() % SegmentSize;
6796 return P.value() < 0 ||
unsigned(
P.value()) == IndexWithinSegment;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static const int BlockSize
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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,...
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 getPerfectShuffleCost(llvm::ArrayRef< int > M)
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 isTRNMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut)
Return true for trn1 or trn2 masks of the form: <0, 8, 2, 10, 4, 12, 6, 14> or <1,...
static const unsigned PerfectShuffleTable[6561+1]