xref: /aosp_15_r20/external/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- X86ShuffleDecodeConstantPool.cpp - X86 shuffle decode -------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // Define several functions to decode x86 specific shuffle semantics using
11*9880d681SAndroid Build Coastguard Worker // constants from the constant pool.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #include "X86ShuffleDecodeConstantPool.h"
16*9880d681SAndroid Build Coastguard Worker #include "Utils/X86ShuffleDecode.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineValueType.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
19*9880d681SAndroid Build Coastguard Worker 
20*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
21*9880d681SAndroid Build Coastguard Worker //  Vector Mask Decoding
22*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
23*9880d681SAndroid Build Coastguard Worker 
24*9880d681SAndroid Build Coastguard Worker namespace llvm {
25*9880d681SAndroid Build Coastguard Worker 
DecodePSHUFBMask(const Constant * C,SmallVectorImpl<int> & ShuffleMask)26*9880d681SAndroid Build Coastguard Worker void DecodePSHUFBMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask) {
27*9880d681SAndroid Build Coastguard Worker   Type *MaskTy = C->getType();
28*9880d681SAndroid Build Coastguard Worker   // It is not an error for the PSHUFB mask to not be a vector of i8 because the
29*9880d681SAndroid Build Coastguard Worker   // constant pool uniques constants by their bit representation.
30*9880d681SAndroid Build Coastguard Worker   // e.g. the following take up the same space in the constant pool:
31*9880d681SAndroid Build Coastguard Worker   //   i128 -170141183420855150465331762880109871104
32*9880d681SAndroid Build Coastguard Worker   //
33*9880d681SAndroid Build Coastguard Worker   //   <2 x i64> <i64 -9223372034707292160, i64 -9223372034707292160>
34*9880d681SAndroid Build Coastguard Worker   //
35*9880d681SAndroid Build Coastguard Worker   //   <4 x i32> <i32 -2147483648, i32 -2147483648,
36*9880d681SAndroid Build Coastguard Worker   //              i32 -2147483648, i32 -2147483648>
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
39*9880d681SAndroid Build Coastguard Worker   unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits();
40*9880d681SAndroid Build Coastguard Worker   assert(MaskTySize == 128 || MaskTySize == 256 || MaskTySize == 512);
41*9880d681SAndroid Build Coastguard Worker #endif
42*9880d681SAndroid Build Coastguard Worker 
43*9880d681SAndroid Build Coastguard Worker   if (!MaskTy->isVectorTy())
44*9880d681SAndroid Build Coastguard Worker     return;
45*9880d681SAndroid Build Coastguard Worker   int NumElts = MaskTy->getVectorNumElements();
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker   Type *EltTy = MaskTy->getVectorElementType();
48*9880d681SAndroid Build Coastguard Worker   if (!EltTy->isIntegerTy())
49*9880d681SAndroid Build Coastguard Worker     return;
50*9880d681SAndroid Build Coastguard Worker 
51*9880d681SAndroid Build Coastguard Worker   // The shuffle mask requires a byte vector - decode cases with
52*9880d681SAndroid Build Coastguard Worker   // wider elements as well.
53*9880d681SAndroid Build Coastguard Worker   unsigned BitWidth = cast<IntegerType>(EltTy)->getBitWidth();
54*9880d681SAndroid Build Coastguard Worker   if ((BitWidth % 8) != 0)
55*9880d681SAndroid Build Coastguard Worker     return;
56*9880d681SAndroid Build Coastguard Worker 
57*9880d681SAndroid Build Coastguard Worker   int Scale = BitWidth / 8;
58*9880d681SAndroid Build Coastguard Worker   int NumBytes = NumElts * Scale;
59*9880d681SAndroid Build Coastguard Worker   ShuffleMask.reserve(NumBytes);
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker   for (int i = 0; i != NumElts; ++i) {
62*9880d681SAndroid Build Coastguard Worker     Constant *COp = C->getAggregateElement(i);
63*9880d681SAndroid Build Coastguard Worker     if (!COp) {
64*9880d681SAndroid Build Coastguard Worker       ShuffleMask.clear();
65*9880d681SAndroid Build Coastguard Worker       return;
66*9880d681SAndroid Build Coastguard Worker     } else if (isa<UndefValue>(COp)) {
67*9880d681SAndroid Build Coastguard Worker       ShuffleMask.append(Scale, SM_SentinelUndef);
68*9880d681SAndroid Build Coastguard Worker       continue;
69*9880d681SAndroid Build Coastguard Worker     }
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker     APInt APElt = cast<ConstantInt>(COp)->getValue();
72*9880d681SAndroid Build Coastguard Worker     for (int j = 0; j != Scale; ++j) {
73*9880d681SAndroid Build Coastguard Worker       // For AVX vectors with 32 bytes the base of the shuffle is the 16-byte
74*9880d681SAndroid Build Coastguard Worker       // lane of the vector we're inside.
75*9880d681SAndroid Build Coastguard Worker       int Base = ((i * Scale) + j) & ~0xf;
76*9880d681SAndroid Build Coastguard Worker 
77*9880d681SAndroid Build Coastguard Worker       uint64_t Element = APElt.getLoBits(8).getZExtValue();
78*9880d681SAndroid Build Coastguard Worker       APElt = APElt.lshr(8);
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker       // If the high bit (7) of the byte is set, the element is zeroed.
81*9880d681SAndroid Build Coastguard Worker       if (Element & (1 << 7))
82*9880d681SAndroid Build Coastguard Worker         ShuffleMask.push_back(SM_SentinelZero);
83*9880d681SAndroid Build Coastguard Worker       else {
84*9880d681SAndroid Build Coastguard Worker         // Only the least significant 4 bits of the byte are used.
85*9880d681SAndroid Build Coastguard Worker         int Index = Base + (Element & 0xf);
86*9880d681SAndroid Build Coastguard Worker         ShuffleMask.push_back(Index);
87*9880d681SAndroid Build Coastguard Worker       }
88*9880d681SAndroid Build Coastguard Worker     }
89*9880d681SAndroid Build Coastguard Worker   }
90*9880d681SAndroid Build Coastguard Worker 
91*9880d681SAndroid Build Coastguard Worker   assert(NumBytes == (int)ShuffleMask.size() && "Unexpected shuffle mask size");
92*9880d681SAndroid Build Coastguard Worker }
93*9880d681SAndroid Build Coastguard Worker 
DecodeVPERMILPMask(const Constant * C,unsigned ElSize,SmallVectorImpl<int> & ShuffleMask)94*9880d681SAndroid Build Coastguard Worker void DecodeVPERMILPMask(const Constant *C, unsigned ElSize,
95*9880d681SAndroid Build Coastguard Worker                         SmallVectorImpl<int> &ShuffleMask) {
96*9880d681SAndroid Build Coastguard Worker   Type *MaskTy = C->getType();
97*9880d681SAndroid Build Coastguard Worker   // It is not an error for the PSHUFB mask to not be a vector of i8 because the
98*9880d681SAndroid Build Coastguard Worker   // constant pool uniques constants by their bit representation.
99*9880d681SAndroid Build Coastguard Worker   // e.g. the following take up the same space in the constant pool:
100*9880d681SAndroid Build Coastguard Worker   //   i128 -170141183420855150465331762880109871104
101*9880d681SAndroid Build Coastguard Worker   //
102*9880d681SAndroid Build Coastguard Worker   //   <2 x i64> <i64 -9223372034707292160, i64 -9223372034707292160>
103*9880d681SAndroid Build Coastguard Worker   //
104*9880d681SAndroid Build Coastguard Worker   //   <4 x i32> <i32 -2147483648, i32 -2147483648,
105*9880d681SAndroid Build Coastguard Worker   //              i32 -2147483648, i32 -2147483648>
106*9880d681SAndroid Build Coastguard Worker 
107*9880d681SAndroid Build Coastguard Worker   if (ElSize != 32 && ElSize != 64)
108*9880d681SAndroid Build Coastguard Worker     return;
109*9880d681SAndroid Build Coastguard Worker 
110*9880d681SAndroid Build Coastguard Worker   unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits();
111*9880d681SAndroid Build Coastguard Worker   if (MaskTySize != 128 && MaskTySize != 256 && MaskTySize != 512)
112*9880d681SAndroid Build Coastguard Worker     return;
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker   // Only support vector types.
115*9880d681SAndroid Build Coastguard Worker   if (!MaskTy->isVectorTy())
116*9880d681SAndroid Build Coastguard Worker     return;
117*9880d681SAndroid Build Coastguard Worker 
118*9880d681SAndroid Build Coastguard Worker   // Make sure its an integer type.
119*9880d681SAndroid Build Coastguard Worker   Type *VecEltTy = MaskTy->getVectorElementType();
120*9880d681SAndroid Build Coastguard Worker   if (!VecEltTy->isIntegerTy())
121*9880d681SAndroid Build Coastguard Worker     return;
122*9880d681SAndroid Build Coastguard Worker 
123*9880d681SAndroid Build Coastguard Worker   // Support any element type from byte up to element size.
124*9880d681SAndroid Build Coastguard Worker   // This is necessary primarily because 64-bit elements get split to 32-bit
125*9880d681SAndroid Build Coastguard Worker   // in the constant pool on 32-bit target.
126*9880d681SAndroid Build Coastguard Worker   unsigned EltTySize = VecEltTy->getIntegerBitWidth();
127*9880d681SAndroid Build Coastguard Worker   if (EltTySize < 8 || EltTySize > ElSize)
128*9880d681SAndroid Build Coastguard Worker     return;
129*9880d681SAndroid Build Coastguard Worker 
130*9880d681SAndroid Build Coastguard Worker   unsigned NumElements = MaskTySize / ElSize;
131*9880d681SAndroid Build Coastguard Worker   assert((NumElements == 2 || NumElements == 4 || NumElements == 8 ||
132*9880d681SAndroid Build Coastguard Worker           NumElements == 16) &&
133*9880d681SAndroid Build Coastguard Worker          "Unexpected number of vector elements.");
134*9880d681SAndroid Build Coastguard Worker   ShuffleMask.reserve(NumElements);
135*9880d681SAndroid Build Coastguard Worker   unsigned NumElementsPerLane = 128 / ElSize;
136*9880d681SAndroid Build Coastguard Worker   unsigned Factor = ElSize / EltTySize;
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < NumElements; ++i) {
139*9880d681SAndroid Build Coastguard Worker     Constant *COp = C->getAggregateElement(i * Factor);
140*9880d681SAndroid Build Coastguard Worker     if (!COp) {
141*9880d681SAndroid Build Coastguard Worker       ShuffleMask.clear();
142*9880d681SAndroid Build Coastguard Worker       return;
143*9880d681SAndroid Build Coastguard Worker     } else if (isa<UndefValue>(COp)) {
144*9880d681SAndroid Build Coastguard Worker       ShuffleMask.push_back(SM_SentinelUndef);
145*9880d681SAndroid Build Coastguard Worker       continue;
146*9880d681SAndroid Build Coastguard Worker     }
147*9880d681SAndroid Build Coastguard Worker     int Index = i & ~(NumElementsPerLane - 1);
148*9880d681SAndroid Build Coastguard Worker     uint64_t Element = cast<ConstantInt>(COp)->getZExtValue();
149*9880d681SAndroid Build Coastguard Worker     if (ElSize == 64)
150*9880d681SAndroid Build Coastguard Worker       Index += (Element >> 1) & 0x1;
151*9880d681SAndroid Build Coastguard Worker     else
152*9880d681SAndroid Build Coastguard Worker       Index += Element & 0x3;
153*9880d681SAndroid Build Coastguard Worker     ShuffleMask.push_back(Index);
154*9880d681SAndroid Build Coastguard Worker   }
155*9880d681SAndroid Build Coastguard Worker 
156*9880d681SAndroid Build Coastguard Worker   // TODO: Handle funny-looking vectors too.
157*9880d681SAndroid Build Coastguard Worker }
158*9880d681SAndroid Build Coastguard Worker 
DecodeVPERMIL2PMask(const Constant * C,unsigned M2Z,unsigned ElSize,SmallVectorImpl<int> & ShuffleMask)159*9880d681SAndroid Build Coastguard Worker void DecodeVPERMIL2PMask(const Constant *C, unsigned M2Z, unsigned ElSize,
160*9880d681SAndroid Build Coastguard Worker                          SmallVectorImpl<int> &ShuffleMask) {
161*9880d681SAndroid Build Coastguard Worker   Type *MaskTy = C->getType();
162*9880d681SAndroid Build Coastguard Worker 
163*9880d681SAndroid Build Coastguard Worker   unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits();
164*9880d681SAndroid Build Coastguard Worker   if (MaskTySize != 128 && MaskTySize != 256)
165*9880d681SAndroid Build Coastguard Worker     return;
166*9880d681SAndroid Build Coastguard Worker 
167*9880d681SAndroid Build Coastguard Worker   // Only support vector types.
168*9880d681SAndroid Build Coastguard Worker   if (!MaskTy->isVectorTy())
169*9880d681SAndroid Build Coastguard Worker     return;
170*9880d681SAndroid Build Coastguard Worker 
171*9880d681SAndroid Build Coastguard Worker   // Make sure its an integer type.
172*9880d681SAndroid Build Coastguard Worker   Type *VecEltTy = MaskTy->getVectorElementType();
173*9880d681SAndroid Build Coastguard Worker   if (!VecEltTy->isIntegerTy())
174*9880d681SAndroid Build Coastguard Worker     return;
175*9880d681SAndroid Build Coastguard Worker 
176*9880d681SAndroid Build Coastguard Worker   // Support any element type from byte up to element size.
177*9880d681SAndroid Build Coastguard Worker   // This is necessary primarily because 64-bit elements get split to 32-bit
178*9880d681SAndroid Build Coastguard Worker   // in the constant pool on 32-bit target.
179*9880d681SAndroid Build Coastguard Worker   unsigned EltTySize = VecEltTy->getIntegerBitWidth();
180*9880d681SAndroid Build Coastguard Worker   if (EltTySize < 8 || EltTySize > ElSize)
181*9880d681SAndroid Build Coastguard Worker     return;
182*9880d681SAndroid Build Coastguard Worker 
183*9880d681SAndroid Build Coastguard Worker   unsigned NumElements = MaskTySize / ElSize;
184*9880d681SAndroid Build Coastguard Worker   assert((NumElements == 2 || NumElements == 4 || NumElements == 8) &&
185*9880d681SAndroid Build Coastguard Worker          "Unexpected number of vector elements.");
186*9880d681SAndroid Build Coastguard Worker   ShuffleMask.reserve(NumElements);
187*9880d681SAndroid Build Coastguard Worker   unsigned NumElementsPerLane = 128 / ElSize;
188*9880d681SAndroid Build Coastguard Worker   unsigned Factor = ElSize / EltTySize;
189*9880d681SAndroid Build Coastguard Worker 
190*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < NumElements; ++i) {
191*9880d681SAndroid Build Coastguard Worker     Constant *COp = C->getAggregateElement(i * Factor);
192*9880d681SAndroid Build Coastguard Worker     if (!COp) {
193*9880d681SAndroid Build Coastguard Worker       ShuffleMask.clear();
194*9880d681SAndroid Build Coastguard Worker       return;
195*9880d681SAndroid Build Coastguard Worker     } else if (isa<UndefValue>(COp)) {
196*9880d681SAndroid Build Coastguard Worker       ShuffleMask.push_back(SM_SentinelUndef);
197*9880d681SAndroid Build Coastguard Worker       continue;
198*9880d681SAndroid Build Coastguard Worker     }
199*9880d681SAndroid Build Coastguard Worker 
200*9880d681SAndroid Build Coastguard Worker     // VPERMIL2 Operation.
201*9880d681SAndroid Build Coastguard Worker     // Bits[3] - Match Bit.
202*9880d681SAndroid Build Coastguard Worker     // Bits[2:1] - (Per Lane) PD Shuffle Mask.
203*9880d681SAndroid Build Coastguard Worker     // Bits[2:0] - (Per Lane) PS Shuffle Mask.
204*9880d681SAndroid Build Coastguard Worker     uint64_t Selector = cast<ConstantInt>(COp)->getZExtValue();
205*9880d681SAndroid Build Coastguard Worker     unsigned MatchBit = (Selector >> 3) & 0x1;
206*9880d681SAndroid Build Coastguard Worker 
207*9880d681SAndroid Build Coastguard Worker     // M2Z[0:1]     MatchBit
208*9880d681SAndroid Build Coastguard Worker     //   0Xb           X        Source selected by Selector index.
209*9880d681SAndroid Build Coastguard Worker     //   10b           0        Source selected by Selector index.
210*9880d681SAndroid Build Coastguard Worker     //   10b           1        Zero.
211*9880d681SAndroid Build Coastguard Worker     //   11b           0        Zero.
212*9880d681SAndroid Build Coastguard Worker     //   11b           1        Source selected by Selector index.
213*9880d681SAndroid Build Coastguard Worker     if ((M2Z & 0x2) != 0u && MatchBit != (M2Z & 0x1)) {
214*9880d681SAndroid Build Coastguard Worker       ShuffleMask.push_back(SM_SentinelZero);
215*9880d681SAndroid Build Coastguard Worker       continue;
216*9880d681SAndroid Build Coastguard Worker     }
217*9880d681SAndroid Build Coastguard Worker 
218*9880d681SAndroid Build Coastguard Worker     int Index = i & ~(NumElementsPerLane - 1);
219*9880d681SAndroid Build Coastguard Worker     if (ElSize == 64)
220*9880d681SAndroid Build Coastguard Worker       Index += (Selector >> 1) & 0x1;
221*9880d681SAndroid Build Coastguard Worker     else
222*9880d681SAndroid Build Coastguard Worker       Index += Selector & 0x3;
223*9880d681SAndroid Build Coastguard Worker 
224*9880d681SAndroid Build Coastguard Worker     int Src = (Selector >> 2) & 0x1;
225*9880d681SAndroid Build Coastguard Worker     Index += Src * NumElements;
226*9880d681SAndroid Build Coastguard Worker     ShuffleMask.push_back(Index);
227*9880d681SAndroid Build Coastguard Worker   }
228*9880d681SAndroid Build Coastguard Worker 
229*9880d681SAndroid Build Coastguard Worker   // TODO: Handle funny-looking vectors too.
230*9880d681SAndroid Build Coastguard Worker }
231*9880d681SAndroid Build Coastguard Worker 
DecodeVPPERMMask(const Constant * C,SmallVectorImpl<int> & ShuffleMask)232*9880d681SAndroid Build Coastguard Worker void DecodeVPPERMMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask) {
233*9880d681SAndroid Build Coastguard Worker   Type *MaskTy = C->getType();
234*9880d681SAndroid Build Coastguard Worker   assert(MaskTy->getPrimitiveSizeInBits() == 128);
235*9880d681SAndroid Build Coastguard Worker 
236*9880d681SAndroid Build Coastguard Worker   // Only support vector types.
237*9880d681SAndroid Build Coastguard Worker   if (!MaskTy->isVectorTy())
238*9880d681SAndroid Build Coastguard Worker     return;
239*9880d681SAndroid Build Coastguard Worker 
240*9880d681SAndroid Build Coastguard Worker   // Make sure its an integer type.
241*9880d681SAndroid Build Coastguard Worker   Type *VecEltTy = MaskTy->getVectorElementType();
242*9880d681SAndroid Build Coastguard Worker   if (!VecEltTy->isIntegerTy())
243*9880d681SAndroid Build Coastguard Worker     return;
244*9880d681SAndroid Build Coastguard Worker 
245*9880d681SAndroid Build Coastguard Worker   // The shuffle mask requires a byte vector - decode cases with
246*9880d681SAndroid Build Coastguard Worker   // wider elements as well.
247*9880d681SAndroid Build Coastguard Worker   unsigned BitWidth = cast<IntegerType>(VecEltTy)->getBitWidth();
248*9880d681SAndroid Build Coastguard Worker   if ((BitWidth % 8) != 0)
249*9880d681SAndroid Build Coastguard Worker     return;
250*9880d681SAndroid Build Coastguard Worker 
251*9880d681SAndroid Build Coastguard Worker   int NumElts = MaskTy->getVectorNumElements();
252*9880d681SAndroid Build Coastguard Worker   int Scale = BitWidth / 8;
253*9880d681SAndroid Build Coastguard Worker   int NumBytes = NumElts * Scale;
254*9880d681SAndroid Build Coastguard Worker   ShuffleMask.reserve(NumBytes);
255*9880d681SAndroid Build Coastguard Worker 
256*9880d681SAndroid Build Coastguard Worker   for (int i = 0; i != NumElts; ++i) {
257*9880d681SAndroid Build Coastguard Worker     Constant *COp = C->getAggregateElement(i);
258*9880d681SAndroid Build Coastguard Worker     if (!COp) {
259*9880d681SAndroid Build Coastguard Worker       ShuffleMask.clear();
260*9880d681SAndroid Build Coastguard Worker       return;
261*9880d681SAndroid Build Coastguard Worker     } else if (isa<UndefValue>(COp)) {
262*9880d681SAndroid Build Coastguard Worker       ShuffleMask.append(Scale, SM_SentinelUndef);
263*9880d681SAndroid Build Coastguard Worker       continue;
264*9880d681SAndroid Build Coastguard Worker     }
265*9880d681SAndroid Build Coastguard Worker 
266*9880d681SAndroid Build Coastguard Worker     // VPPERM Operation
267*9880d681SAndroid Build Coastguard Worker     // Bits[4:0] - Byte Index (0 - 31)
268*9880d681SAndroid Build Coastguard Worker     // Bits[7:5] - Permute Operation
269*9880d681SAndroid Build Coastguard Worker     //
270*9880d681SAndroid Build Coastguard Worker     // Permute Operation:
271*9880d681SAndroid Build Coastguard Worker     // 0 - Source byte (no logical operation).
272*9880d681SAndroid Build Coastguard Worker     // 1 - Invert source byte.
273*9880d681SAndroid Build Coastguard Worker     // 2 - Bit reverse of source byte.
274*9880d681SAndroid Build Coastguard Worker     // 3 - Bit reverse of inverted source byte.
275*9880d681SAndroid Build Coastguard Worker     // 4 - 00h (zero - fill).
276*9880d681SAndroid Build Coastguard Worker     // 5 - FFh (ones - fill).
277*9880d681SAndroid Build Coastguard Worker     // 6 - Most significant bit of source byte replicated in all bit positions.
278*9880d681SAndroid Build Coastguard Worker     // 7 - Invert most significant bit of source byte and replicate in all bit positions.
279*9880d681SAndroid Build Coastguard Worker     APInt MaskElt = cast<ConstantInt>(COp)->getValue();
280*9880d681SAndroid Build Coastguard Worker     for (int j = 0; j != Scale; ++j) {
281*9880d681SAndroid Build Coastguard Worker       APInt Index = MaskElt.getLoBits(5);
282*9880d681SAndroid Build Coastguard Worker       APInt PermuteOp = MaskElt.lshr(5).getLoBits(3);
283*9880d681SAndroid Build Coastguard Worker       MaskElt = MaskElt.lshr(8);
284*9880d681SAndroid Build Coastguard Worker 
285*9880d681SAndroid Build Coastguard Worker       if (PermuteOp == 4) {
286*9880d681SAndroid Build Coastguard Worker         ShuffleMask.push_back(SM_SentinelZero);
287*9880d681SAndroid Build Coastguard Worker         continue;
288*9880d681SAndroid Build Coastguard Worker       }
289*9880d681SAndroid Build Coastguard Worker       if (PermuteOp != 0) {
290*9880d681SAndroid Build Coastguard Worker         ShuffleMask.clear();
291*9880d681SAndroid Build Coastguard Worker         return;
292*9880d681SAndroid Build Coastguard Worker       }
293*9880d681SAndroid Build Coastguard Worker       ShuffleMask.push_back((int)Index.getZExtValue());
294*9880d681SAndroid Build Coastguard Worker     }
295*9880d681SAndroid Build Coastguard Worker   }
296*9880d681SAndroid Build Coastguard Worker 
297*9880d681SAndroid Build Coastguard Worker   assert(NumBytes == (int)ShuffleMask.size() && "Unexpected shuffle mask size");
298*9880d681SAndroid Build Coastguard Worker }
299*9880d681SAndroid Build Coastguard Worker 
DecodeVPERMVMask(const Constant * C,MVT VT,SmallVectorImpl<int> & ShuffleMask)300*9880d681SAndroid Build Coastguard Worker void DecodeVPERMVMask(const Constant *C, MVT VT,
301*9880d681SAndroid Build Coastguard Worker                       SmallVectorImpl<int> &ShuffleMask) {
302*9880d681SAndroid Build Coastguard Worker   Type *MaskTy = C->getType();
303*9880d681SAndroid Build Coastguard Worker   if (MaskTy->isVectorTy()) {
304*9880d681SAndroid Build Coastguard Worker     unsigned NumElements = MaskTy->getVectorNumElements();
305*9880d681SAndroid Build Coastguard Worker     if (NumElements == VT.getVectorNumElements()) {
306*9880d681SAndroid Build Coastguard Worker       unsigned EltMaskSize = Log2_64(NumElements);
307*9880d681SAndroid Build Coastguard Worker       for (unsigned i = 0; i < NumElements; ++i) {
308*9880d681SAndroid Build Coastguard Worker         Constant *COp = C->getAggregateElement(i);
309*9880d681SAndroid Build Coastguard Worker         if (!COp || (!isa<UndefValue>(COp) && !isa<ConstantInt>(COp))) {
310*9880d681SAndroid Build Coastguard Worker           ShuffleMask.clear();
311*9880d681SAndroid Build Coastguard Worker           return;
312*9880d681SAndroid Build Coastguard Worker         }
313*9880d681SAndroid Build Coastguard Worker         if (isa<UndefValue>(COp))
314*9880d681SAndroid Build Coastguard Worker           ShuffleMask.push_back(SM_SentinelUndef);
315*9880d681SAndroid Build Coastguard Worker         else {
316*9880d681SAndroid Build Coastguard Worker           APInt Element = cast<ConstantInt>(COp)->getValue();
317*9880d681SAndroid Build Coastguard Worker           Element = Element.getLoBits(EltMaskSize);
318*9880d681SAndroid Build Coastguard Worker           ShuffleMask.push_back(Element.getZExtValue());
319*9880d681SAndroid Build Coastguard Worker         }
320*9880d681SAndroid Build Coastguard Worker       }
321*9880d681SAndroid Build Coastguard Worker     }
322*9880d681SAndroid Build Coastguard Worker     return;
323*9880d681SAndroid Build Coastguard Worker   }
324*9880d681SAndroid Build Coastguard Worker   // Scalar value; just broadcast it
325*9880d681SAndroid Build Coastguard Worker   if (!isa<ConstantInt>(C))
326*9880d681SAndroid Build Coastguard Worker     return;
327*9880d681SAndroid Build Coastguard Worker   uint64_t Element = cast<ConstantInt>(C)->getZExtValue();
328*9880d681SAndroid Build Coastguard Worker   int NumElements = VT.getVectorNumElements();
329*9880d681SAndroid Build Coastguard Worker   Element &= (1 << NumElements) - 1;
330*9880d681SAndroid Build Coastguard Worker   for (int i = 0; i < NumElements; ++i)
331*9880d681SAndroid Build Coastguard Worker     ShuffleMask.push_back(Element);
332*9880d681SAndroid Build Coastguard Worker }
333*9880d681SAndroid Build Coastguard Worker 
DecodeVPERMV3Mask(const Constant * C,MVT VT,SmallVectorImpl<int> & ShuffleMask)334*9880d681SAndroid Build Coastguard Worker void DecodeVPERMV3Mask(const Constant *C, MVT VT,
335*9880d681SAndroid Build Coastguard Worker                        SmallVectorImpl<int> &ShuffleMask) {
336*9880d681SAndroid Build Coastguard Worker   Type *MaskTy = C->getType();
337*9880d681SAndroid Build Coastguard Worker   unsigned NumElements = MaskTy->getVectorNumElements();
338*9880d681SAndroid Build Coastguard Worker   if (NumElements == VT.getVectorNumElements()) {
339*9880d681SAndroid Build Coastguard Worker     unsigned EltMaskSize = Log2_64(NumElements * 2);
340*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0; i < NumElements; ++i) {
341*9880d681SAndroid Build Coastguard Worker       Constant *COp = C->getAggregateElement(i);
342*9880d681SAndroid Build Coastguard Worker       if (!COp) {
343*9880d681SAndroid Build Coastguard Worker         ShuffleMask.clear();
344*9880d681SAndroid Build Coastguard Worker         return;
345*9880d681SAndroid Build Coastguard Worker       }
346*9880d681SAndroid Build Coastguard Worker       if (isa<UndefValue>(COp))
347*9880d681SAndroid Build Coastguard Worker         ShuffleMask.push_back(SM_SentinelUndef);
348*9880d681SAndroid Build Coastguard Worker       else {
349*9880d681SAndroid Build Coastguard Worker         APInt Element = cast<ConstantInt>(COp)->getValue();
350*9880d681SAndroid Build Coastguard Worker         Element = Element.getLoBits(EltMaskSize);
351*9880d681SAndroid Build Coastguard Worker         ShuffleMask.push_back(Element.getZExtValue());
352*9880d681SAndroid Build Coastguard Worker       }
353*9880d681SAndroid Build Coastguard Worker     }
354*9880d681SAndroid Build Coastguard Worker   }
355*9880d681SAndroid Build Coastguard Worker }
356*9880d681SAndroid Build Coastguard Worker } // llvm namespace
357