xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
10b57cec5SDimitry Andric //===-- X86ShuffleDecodeConstantPool.cpp - X86 shuffle decode -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Define several functions to decode x86 specific shuffle semantics using
100b57cec5SDimitry Andric // constants from the constant pool.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
145ffd83dbSDimitry Andric #include "X86ShuffleDecodeConstantPool.h"
155ffd83dbSDimitry Andric #include "MCTargetDesc/X86ShuffleDecode.h"
160b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
175ffd83dbSDimitry Andric #include "llvm/ADT/SmallVector.h"
180b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
210b57cec5SDimitry Andric //  Vector Mask Decoding
220b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace llvm {
250b57cec5SDimitry Andric 
extractConstantMask(const Constant * C,unsigned MaskEltSizeInBits,APInt & UndefElts,SmallVectorImpl<uint64_t> & RawMask)260b57cec5SDimitry Andric static bool extractConstantMask(const Constant *C, unsigned MaskEltSizeInBits,
270b57cec5SDimitry Andric                                 APInt &UndefElts,
280b57cec5SDimitry Andric                                 SmallVectorImpl<uint64_t> &RawMask) {
290b57cec5SDimitry Andric   // It is not an error for shuffle masks to not be a vector of
300b57cec5SDimitry Andric   // MaskEltSizeInBits because the constant pool uniques constants by their
310b57cec5SDimitry Andric   // bit representation.
320b57cec5SDimitry Andric   // e.g. the following take up the same space in the constant pool:
330b57cec5SDimitry Andric   //   i128 -170141183420855150465331762880109871104
340b57cec5SDimitry Andric   //
350b57cec5SDimitry Andric   //   <2 x i64> <i64 -9223372034707292160, i64 -9223372034707292160>
360b57cec5SDimitry Andric   //
370b57cec5SDimitry Andric   //   <4 x i32> <i32 -2147483648, i32 -2147483648,
380b57cec5SDimitry Andric   //              i32 -2147483648, i32 -2147483648>
395ffd83dbSDimitry Andric   auto *CstTy = dyn_cast<FixedVectorType>(C->getType());
405ffd83dbSDimitry Andric   if (!CstTy)
410b57cec5SDimitry Andric     return false;
420b57cec5SDimitry Andric 
435ffd83dbSDimitry Andric   Type *CstEltTy = CstTy->getElementType();
440b57cec5SDimitry Andric   if (!CstEltTy->isIntegerTy())
450b57cec5SDimitry Andric     return false;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric   unsigned CstSizeInBits = CstTy->getPrimitiveSizeInBits();
480b57cec5SDimitry Andric   unsigned CstEltSizeInBits = CstTy->getScalarSizeInBits();
495ffd83dbSDimitry Andric   unsigned NumCstElts = CstTy->getNumElements();
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   assert((CstSizeInBits % MaskEltSizeInBits) == 0 &&
520b57cec5SDimitry Andric          "Unaligned shuffle mask size");
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   unsigned NumMaskElts = CstSizeInBits / MaskEltSizeInBits;
550b57cec5SDimitry Andric   UndefElts = APInt(NumMaskElts, 0);
560b57cec5SDimitry Andric   RawMask.resize(NumMaskElts, 0);
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   // Fast path - if the constants match the mask size then copy direct.
590b57cec5SDimitry Andric   if (MaskEltSizeInBits == CstEltSizeInBits) {
600b57cec5SDimitry Andric     assert(NumCstElts == NumMaskElts && "Unaligned shuffle mask size");
610b57cec5SDimitry Andric     for (unsigned i = 0; i != NumMaskElts; ++i) {
620b57cec5SDimitry Andric       Constant *COp = C->getAggregateElement(i);
630b57cec5SDimitry Andric       if (!COp || (!isa<UndefValue>(COp) && !isa<ConstantInt>(COp)))
640b57cec5SDimitry Andric         return false;
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric       if (isa<UndefValue>(COp)) {
670b57cec5SDimitry Andric         UndefElts.setBit(i);
680b57cec5SDimitry Andric         RawMask[i] = 0;
690b57cec5SDimitry Andric         continue;
700b57cec5SDimitry Andric       }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric       auto *Elt = cast<ConstantInt>(COp);
730b57cec5SDimitry Andric       RawMask[i] = Elt->getValue().getZExtValue();
740b57cec5SDimitry Andric     }
750b57cec5SDimitry Andric     return true;
760b57cec5SDimitry Andric   }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   // Extract all the undef/constant element data and pack into single bitsets.
790b57cec5SDimitry Andric   APInt UndefBits(CstSizeInBits, 0);
800b57cec5SDimitry Andric   APInt MaskBits(CstSizeInBits, 0);
810b57cec5SDimitry Andric   for (unsigned i = 0; i != NumCstElts; ++i) {
820b57cec5SDimitry Andric     Constant *COp = C->getAggregateElement(i);
830b57cec5SDimitry Andric     if (!COp || (!isa<UndefValue>(COp) && !isa<ConstantInt>(COp)))
840b57cec5SDimitry Andric       return false;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric     unsigned BitOffset = i * CstEltSizeInBits;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric     if (isa<UndefValue>(COp)) {
890b57cec5SDimitry Andric       UndefBits.setBits(BitOffset, BitOffset + CstEltSizeInBits);
900b57cec5SDimitry Andric       continue;
910b57cec5SDimitry Andric     }
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric     MaskBits.insertBits(cast<ConstantInt>(COp)->getValue(), BitOffset);
940b57cec5SDimitry Andric   }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   // Now extract the undef/constant bit data into the raw shuffle masks.
970b57cec5SDimitry Andric   for (unsigned i = 0; i != NumMaskElts; ++i) {
980b57cec5SDimitry Andric     unsigned BitOffset = i * MaskEltSizeInBits;
990b57cec5SDimitry Andric     APInt EltUndef = UndefBits.extractBits(MaskEltSizeInBits, BitOffset);
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric     // Only treat the element as UNDEF if all bits are UNDEF, otherwise
1020b57cec5SDimitry Andric     // treat it as zero.
103*349cc55cSDimitry Andric     if (EltUndef.isAllOnes()) {
1040b57cec5SDimitry Andric       UndefElts.setBit(i);
1050b57cec5SDimitry Andric       RawMask[i] = 0;
1060b57cec5SDimitry Andric       continue;
1070b57cec5SDimitry Andric     }
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric     APInt EltBits = MaskBits.extractBits(MaskEltSizeInBits, BitOffset);
1100b57cec5SDimitry Andric     RawMask[i] = EltBits.getZExtValue();
1110b57cec5SDimitry Andric   }
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   return true;
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric 
DecodePSHUFBMask(const Constant * C,unsigned Width,SmallVectorImpl<int> & ShuffleMask)1160b57cec5SDimitry Andric void DecodePSHUFBMask(const Constant *C, unsigned Width,
1170b57cec5SDimitry Andric                       SmallVectorImpl<int> &ShuffleMask) {
1180b57cec5SDimitry Andric   assert((Width == 128 || Width == 256 || Width == 512) &&
1190b57cec5SDimitry Andric          C->getType()->getPrimitiveSizeInBits() >= Width &&
1200b57cec5SDimitry Andric          "Unexpected vector size.");
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   // The shuffle mask requires a byte vector.
1230b57cec5SDimitry Andric   APInt UndefElts;
1240b57cec5SDimitry Andric   SmallVector<uint64_t, 64> RawMask;
1250b57cec5SDimitry Andric   if (!extractConstantMask(C, 8, UndefElts, RawMask))
1260b57cec5SDimitry Andric     return;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   unsigned NumElts = Width / 8;
1290b57cec5SDimitry Andric   assert((NumElts == 16 || NumElts == 32 || NumElts == 64) &&
1300b57cec5SDimitry Andric          "Unexpected number of vector elements.");
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   for (unsigned i = 0; i != NumElts; ++i) {
1330b57cec5SDimitry Andric     if (UndefElts[i]) {
1340b57cec5SDimitry Andric       ShuffleMask.push_back(SM_SentinelUndef);
1350b57cec5SDimitry Andric       continue;
1360b57cec5SDimitry Andric     }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric     uint64_t Element = RawMask[i];
1390b57cec5SDimitry Andric     // If the high bit (7) of the byte is set, the element is zeroed.
1400b57cec5SDimitry Andric     if (Element & (1 << 7))
1410b57cec5SDimitry Andric       ShuffleMask.push_back(SM_SentinelZero);
1420b57cec5SDimitry Andric     else {
1430b57cec5SDimitry Andric       // For AVX vectors with 32 bytes the base of the shuffle is the 16-byte
1440b57cec5SDimitry Andric       // lane of the vector we're inside.
1450b57cec5SDimitry Andric       unsigned Base = i & ~0xf;
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric       // Only the least significant 4 bits of the byte are used.
1480b57cec5SDimitry Andric       int Index = Base + (Element & 0xf);
1490b57cec5SDimitry Andric       ShuffleMask.push_back(Index);
1500b57cec5SDimitry Andric     }
1510b57cec5SDimitry Andric   }
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
DecodeVPERMILPMask(const Constant * C,unsigned ElSize,unsigned Width,SmallVectorImpl<int> & ShuffleMask)1540b57cec5SDimitry Andric void DecodeVPERMILPMask(const Constant *C, unsigned ElSize, unsigned Width,
1550b57cec5SDimitry Andric                         SmallVectorImpl<int> &ShuffleMask) {
1560b57cec5SDimitry Andric   assert((Width == 128 || Width == 256 || Width == 512) &&
1570b57cec5SDimitry Andric          C->getType()->getPrimitiveSizeInBits() >= Width &&
1580b57cec5SDimitry Andric          "Unexpected vector size.");
1590b57cec5SDimitry Andric   assert((ElSize == 32 || ElSize == 64) && "Unexpected vector element size.");
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   // The shuffle mask requires elements the same size as the target.
1620b57cec5SDimitry Andric   APInt UndefElts;
1630b57cec5SDimitry Andric   SmallVector<uint64_t, 16> RawMask;
1640b57cec5SDimitry Andric   if (!extractConstantMask(C, ElSize, UndefElts, RawMask))
1650b57cec5SDimitry Andric     return;
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   unsigned NumElts = Width / ElSize;
1680b57cec5SDimitry Andric   unsigned NumEltsPerLane = 128 / ElSize;
1690b57cec5SDimitry Andric   assert((NumElts == 2 || NumElts == 4 || NumElts == 8 || NumElts == 16) &&
1700b57cec5SDimitry Andric          "Unexpected number of vector elements.");
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   for (unsigned i = 0; i != NumElts; ++i) {
1730b57cec5SDimitry Andric     if (UndefElts[i]) {
1740b57cec5SDimitry Andric       ShuffleMask.push_back(SM_SentinelUndef);
1750b57cec5SDimitry Andric       continue;
1760b57cec5SDimitry Andric     }
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric     int Index = i & ~(NumEltsPerLane - 1);
1790b57cec5SDimitry Andric     uint64_t Element = RawMask[i];
1800b57cec5SDimitry Andric     if (ElSize == 64)
1810b57cec5SDimitry Andric       Index += (Element >> 1) & 0x1;
1820b57cec5SDimitry Andric     else
1830b57cec5SDimitry Andric       Index += Element & 0x3;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric     ShuffleMask.push_back(Index);
1860b57cec5SDimitry Andric   }
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
DecodeVPERMIL2PMask(const Constant * C,unsigned M2Z,unsigned ElSize,unsigned Width,SmallVectorImpl<int> & ShuffleMask)1890b57cec5SDimitry Andric void DecodeVPERMIL2PMask(const Constant *C, unsigned M2Z, unsigned ElSize,
1905ffd83dbSDimitry Andric                          unsigned Width, SmallVectorImpl<int> &ShuffleMask) {
1910b57cec5SDimitry Andric   Type *MaskTy = C->getType();
1920b57cec5SDimitry Andric   unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits();
1930b57cec5SDimitry Andric   (void)MaskTySize;
1945ffd83dbSDimitry Andric   assert((MaskTySize == 128 || MaskTySize == 256) && Width >= MaskTySize &&
1955ffd83dbSDimitry Andric          "Unexpected vector size.");
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   // The shuffle mask requires elements the same size as the target.
1980b57cec5SDimitry Andric   APInt UndefElts;
1990b57cec5SDimitry Andric   SmallVector<uint64_t, 8> RawMask;
2000b57cec5SDimitry Andric   if (!extractConstantMask(C, ElSize, UndefElts, RawMask))
2010b57cec5SDimitry Andric     return;
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   unsigned NumElts = Width / ElSize;
2040b57cec5SDimitry Andric   unsigned NumEltsPerLane = 128 / ElSize;
2050b57cec5SDimitry Andric   assert((NumElts == 2 || NumElts == 4 || NumElts == 8) &&
2060b57cec5SDimitry Andric          "Unexpected number of vector elements.");
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   for (unsigned i = 0; i != NumElts; ++i) {
2090b57cec5SDimitry Andric     if (UndefElts[i]) {
2100b57cec5SDimitry Andric       ShuffleMask.push_back(SM_SentinelUndef);
2110b57cec5SDimitry Andric       continue;
2120b57cec5SDimitry Andric     }
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric     // VPERMIL2 Operation.
2150b57cec5SDimitry Andric     // Bits[3] - Match Bit.
2160b57cec5SDimitry Andric     // Bits[2:1] - (Per Lane) PD Shuffle Mask.
2170b57cec5SDimitry Andric     // Bits[2:0] - (Per Lane) PS Shuffle Mask.
2180b57cec5SDimitry Andric     uint64_t Selector = RawMask[i];
2190b57cec5SDimitry Andric     unsigned MatchBit = (Selector >> 3) & 0x1;
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric     // M2Z[0:1]     MatchBit
2220b57cec5SDimitry Andric     //   0Xb           X        Source selected by Selector index.
2230b57cec5SDimitry Andric     //   10b           0        Source selected by Selector index.
2240b57cec5SDimitry Andric     //   10b           1        Zero.
2250b57cec5SDimitry Andric     //   11b           0        Zero.
2260b57cec5SDimitry Andric     //   11b           1        Source selected by Selector index.
2270b57cec5SDimitry Andric     if ((M2Z & 0x2) != 0u && MatchBit != (M2Z & 0x1)) {
2280b57cec5SDimitry Andric       ShuffleMask.push_back(SM_SentinelZero);
2290b57cec5SDimitry Andric       continue;
2300b57cec5SDimitry Andric     }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric     int Index = i & ~(NumEltsPerLane - 1);
2330b57cec5SDimitry Andric     if (ElSize == 64)
2340b57cec5SDimitry Andric       Index += (Selector >> 1) & 0x1;
2350b57cec5SDimitry Andric     else
2360b57cec5SDimitry Andric       Index += Selector & 0x3;
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric     int Src = (Selector >> 2) & 0x1;
2390b57cec5SDimitry Andric     Index += Src * NumElts;
2400b57cec5SDimitry Andric     ShuffleMask.push_back(Index);
2410b57cec5SDimitry Andric   }
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric 
DecodeVPPERMMask(const Constant * C,unsigned Width,SmallVectorImpl<int> & ShuffleMask)2440b57cec5SDimitry Andric void DecodeVPPERMMask(const Constant *C, unsigned Width,
2450b57cec5SDimitry Andric                       SmallVectorImpl<int> &ShuffleMask) {
2460b57cec5SDimitry Andric   Type *MaskTy = C->getType();
2470b57cec5SDimitry Andric   unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits();
2480b57cec5SDimitry Andric   (void)MaskTySize;
2490b57cec5SDimitry Andric   assert(Width == 128 && Width >= MaskTySize && "Unexpected vector size.");
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric   // The shuffle mask requires a byte vector.
2520b57cec5SDimitry Andric   APInt UndefElts;
2530b57cec5SDimitry Andric   SmallVector<uint64_t, 16> RawMask;
2540b57cec5SDimitry Andric   if (!extractConstantMask(C, 8, UndefElts, RawMask))
2550b57cec5SDimitry Andric     return;
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   unsigned NumElts = Width / 8;
2580b57cec5SDimitry Andric   assert(NumElts == 16 && "Unexpected number of vector elements.");
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   for (unsigned i = 0; i != NumElts; ++i) {
2610b57cec5SDimitry Andric     if (UndefElts[i]) {
2620b57cec5SDimitry Andric       ShuffleMask.push_back(SM_SentinelUndef);
2630b57cec5SDimitry Andric       continue;
2640b57cec5SDimitry Andric     }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric     // VPPERM Operation
2670b57cec5SDimitry Andric     // Bits[4:0] - Byte Index (0 - 31)
2680b57cec5SDimitry Andric     // Bits[7:5] - Permute Operation
2690b57cec5SDimitry Andric     //
2700b57cec5SDimitry Andric     // Permute Operation:
2710b57cec5SDimitry Andric     // 0 - Source byte (no logical operation).
2720b57cec5SDimitry Andric     // 1 - Invert source byte.
2730b57cec5SDimitry Andric     // 2 - Bit reverse of source byte.
2740b57cec5SDimitry Andric     // 3 - Bit reverse of inverted source byte.
2750b57cec5SDimitry Andric     // 4 - 00h (zero - fill).
2760b57cec5SDimitry Andric     // 5 - FFh (ones - fill).
2770b57cec5SDimitry Andric     // 6 - Most significant bit of source byte replicated in all bit positions.
2780b57cec5SDimitry Andric     // 7 - Invert most significant bit of source byte and replicate in all bit
2790b57cec5SDimitry Andric     // positions.
2800b57cec5SDimitry Andric     uint64_t Element = RawMask[i];
2810b57cec5SDimitry Andric     uint64_t Index = Element & 0x1F;
2820b57cec5SDimitry Andric     uint64_t PermuteOp = (Element >> 5) & 0x7;
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric     if (PermuteOp == 4) {
2850b57cec5SDimitry Andric       ShuffleMask.push_back(SM_SentinelZero);
2860b57cec5SDimitry Andric       continue;
2870b57cec5SDimitry Andric     }
2880b57cec5SDimitry Andric     if (PermuteOp != 0) {
2890b57cec5SDimitry Andric       ShuffleMask.clear();
2900b57cec5SDimitry Andric       return;
2910b57cec5SDimitry Andric     }
2920b57cec5SDimitry Andric     ShuffleMask.push_back((int)Index);
2930b57cec5SDimitry Andric   }
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric 
296e8d8bef9SDimitry Andric } // namespace llvm
297