blob: a202fc63637b9576bffc2d9320b7559f0771a1a5 [file] [log] [blame]
Craig Topper69653af2015-12-31 22:40:45 +00001//===-- X86ShuffleDecodeConstantPool.cpp - X86 shuffle decode -------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Craig Topper69653af2015-12-31 22:40:45 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Define several functions to decode x86 specific shuffle semantics using
10// constants from the constant pool.
11//
12//===----------------------------------------------------------------------===//
13
Craig Topper69653af2015-12-31 22:40:45 +000014#include "Utils/X86ShuffleDecode.h"
Craig Topper53e5a38d2017-02-27 16:15:25 +000015#include "llvm/ADT/APInt.h"
Craig Topper69653af2015-12-31 22:40:45 +000016#include "llvm/IR/Constants.h"
17
18//===----------------------------------------------------------------------===//
19// Vector Mask Decoding
20//===----------------------------------------------------------------------===//
21
22namespace llvm {
23
Simon Pilgrim97a48202016-09-29 15:25:48 +000024static bool extractConstantMask(const Constant *C, unsigned MaskEltSizeInBits,
Craig Topper53e5a38d2017-02-27 16:15:25 +000025 APInt &UndefElts,
Simon Pilgrim97a48202016-09-29 15:25:48 +000026 SmallVectorImpl<uint64_t> &RawMask) {
27 // It is not an error for shuffle masks to not be a vector of
28 // MaskEltSizeInBits because the constant pool uniques constants by their
29 // bit representation.
Craig Topper69653af2015-12-31 22:40:45 +000030 // e.g. the following take up the same space in the constant pool:
31 // i128 -170141183420855150465331762880109871104
32 //
33 // <2 x i64> <i64 -9223372034707292160, i64 -9223372034707292160>
34 //
35 // <4 x i32> <i32 -2147483648, i32 -2147483648,
36 // i32 -2147483648, i32 -2147483648>
Simon Pilgrim97a48202016-09-29 15:25:48 +000037 Type *CstTy = C->getType();
38 if (!CstTy->isVectorTy())
39 return false;
Craig Topper69653af2015-12-31 22:40:45 +000040
Simon Pilgrim97a48202016-09-29 15:25:48 +000041 Type *CstEltTy = CstTy->getVectorElementType();
42 if (!CstEltTy->isIntegerTy())
43 return false;
Craig Topper69653af2015-12-31 22:40:45 +000044
Simon Pilgrim97a48202016-09-29 15:25:48 +000045 unsigned CstSizeInBits = CstTy->getPrimitiveSizeInBits();
46 unsigned CstEltSizeInBits = CstTy->getScalarSizeInBits();
47 unsigned NumCstElts = CstTy->getVectorNumElements();
Craig Topper69653af2015-12-31 22:40:45 +000048
Simon Pilgrime86b7e22017-03-09 14:06:39 +000049 assert((CstSizeInBits % MaskEltSizeInBits) == 0 &&
50 "Unaligned shuffle mask size");
51
52 unsigned NumMaskElts = CstSizeInBits / MaskEltSizeInBits;
53 UndefElts = APInt(NumMaskElts, 0);
54 RawMask.resize(NumMaskElts, 0);
55
56 // Fast path - if the constants match the mask size then copy direct.
57 if (MaskEltSizeInBits == CstEltSizeInBits) {
58 assert(NumCstElts == NumMaskElts && "Unaligned shuffle mask size");
59 for (unsigned i = 0; i != NumMaskElts; ++i) {
60 Constant *COp = C->getAggregateElement(i);
61 if (!COp || (!isa<UndefValue>(COp) && !isa<ConstantInt>(COp)))
62 return false;
63
64 if (isa<UndefValue>(COp)) {
65 UndefElts.setBit(i);
66 RawMask[i] = 0;
67 continue;
68 }
69
70 auto *Elt = cast<ConstantInt>(COp);
71 RawMask[i] = Elt->getValue().getZExtValue();
72 }
73 return true;
74 }
75
Simon Pilgrim97a48202016-09-29 15:25:48 +000076 // Extract all the undef/constant element data and pack into single bitsets.
77 APInt UndefBits(CstSizeInBits, 0);
78 APInt MaskBits(CstSizeInBits, 0);
79 for (unsigned i = 0; i != NumCstElts; ++i) {
Simon Pilgrim05e48b92016-02-18 10:17:40 +000080 Constant *COp = C->getAggregateElement(i);
Simon Pilgrim97a48202016-09-29 15:25:48 +000081 if (!COp || (!isa<UndefValue>(COp) && !isa<ConstantInt>(COp)))
82 return false;
83
Simon Pilgrim3a895c42017-02-22 15:04:55 +000084 unsigned BitOffset = i * CstEltSizeInBits;
85
Simon Pilgrim97a48202016-09-29 15:25:48 +000086 if (isa<UndefValue>(COp)) {
Simon Pilgrimaed35222017-02-24 10:15:29 +000087 UndefBits.setBits(BitOffset, BitOffset + CstEltSizeInBits);
Simon Pilgrim05e48b92016-02-18 10:17:40 +000088 continue;
89 }
90
Simon Pilgrimb02667c2017-03-10 13:44:32 +000091 MaskBits.insertBits(cast<ConstantInt>(COp)->getValue(), BitOffset);
Craig Topper69653af2015-12-31 22:40:45 +000092 }
Simon Pilgrim05e48b92016-02-18 10:17:40 +000093
Simon Pilgrim97a48202016-09-29 15:25:48 +000094 // Now extract the undef/constant bit data into the raw shuffle masks.
Simon Pilgrim97a48202016-09-29 15:25:48 +000095 for (unsigned i = 0; i != NumMaskElts; ++i) {
Simon Pilgrim0f5fb5f2017-02-25 20:01:58 +000096 unsigned BitOffset = i * MaskEltSizeInBits;
97 APInt EltUndef = UndefBits.extractBits(MaskEltSizeInBits, BitOffset);
Simon Pilgrim97a48202016-09-29 15:25:48 +000098
99 // Only treat the element as UNDEF if all bits are UNDEF, otherwise
100 // treat it as zero.
Simon Pilgrim96ef0c12016-10-23 15:09:44 +0000101 if (EltUndef.isAllOnesValue()) {
Craig Topper53e5a38d2017-02-27 16:15:25 +0000102 UndefElts.setBit(i);
Simon Pilgrim97a48202016-09-29 15:25:48 +0000103 RawMask[i] = 0;
104 continue;
105 }
106
Simon Pilgrim0f5fb5f2017-02-25 20:01:58 +0000107 APInt EltBits = MaskBits.extractBits(MaskEltSizeInBits, BitOffset);
Simon Pilgrim97a48202016-09-29 15:25:48 +0000108 RawMask[i] = EltBits.getZExtValue();
109 }
110
111 return true;
112}
113
Craig Topperc8e183f2018-10-22 22:14:05 +0000114void DecodePSHUFBMask(const Constant *C, unsigned Width,
115 SmallVectorImpl<int> &ShuffleMask) {
116 assert((Width == 128 || Width == 256 || Width == 512) &&
117 C->getType()->getPrimitiveSizeInBits() >= Width &&
Simon Pilgrim630dd6f2016-10-01 20:12:56 +0000118 "Unexpected vector size.");
Simon Pilgrim97a48202016-09-29 15:25:48 +0000119
120 // The shuffle mask requires a byte vector.
Craig Topper53e5a38d2017-02-27 16:15:25 +0000121 APInt UndefElts;
Craig Toppere1be95c2017-02-27 16:15:27 +0000122 SmallVector<uint64_t, 64> RawMask;
Simon Pilgrim97a48202016-09-29 15:25:48 +0000123 if (!extractConstantMask(C, 8, UndefElts, RawMask))
124 return;
125
Craig Topperc8e183f2018-10-22 22:14:05 +0000126 unsigned NumElts = Width / 8;
Simon Pilgrim97a48202016-09-29 15:25:48 +0000127 assert((NumElts == 16 || NumElts == 32 || NumElts == 64) &&
128 "Unexpected number of vector elements.");
129
130 for (unsigned i = 0; i != NumElts; ++i) {
131 if (UndefElts[i]) {
132 ShuffleMask.push_back(SM_SentinelUndef);
133 continue;
134 }
135
136 uint64_t Element = RawMask[i];
137 // If the high bit (7) of the byte is set, the element is zeroed.
138 if (Element & (1 << 7))
139 ShuffleMask.push_back(SM_SentinelZero);
140 else {
141 // For AVX vectors with 32 bytes the base of the shuffle is the 16-byte
142 // lane of the vector we're inside.
143 unsigned Base = i & ~0xf;
144
145 // Only the least significant 4 bits of the byte are used.
146 int Index = Base + (Element & 0xf);
147 ShuffleMask.push_back(Index);
148 }
149 }
Craig Topper69653af2015-12-31 22:40:45 +0000150}
151
Craig Topperc8e183f2018-10-22 22:14:05 +0000152void DecodeVPERMILPMask(const Constant *C, unsigned ElSize, unsigned Width,
Craig Topper69653af2015-12-31 22:40:45 +0000153 SmallVectorImpl<int> &ShuffleMask) {
Craig Topperc8e183f2018-10-22 22:14:05 +0000154 assert((Width == 128 || Width == 256 || Width == 512) &&
155 C->getType()->getPrimitiveSizeInBits() >= Width &&
Simon Pilgrim630dd6f2016-10-01 20:12:56 +0000156 "Unexpected vector size.");
157 assert((ElSize == 32 || ElSize == 64) && "Unexpected vector element size.");
Simon Pilgrim97a48202016-09-29 15:25:48 +0000158
159 // The shuffle mask requires elements the same size as the target.
Craig Topper53e5a38d2017-02-27 16:15:25 +0000160 APInt UndefElts;
Craig Toppere1be95c2017-02-27 16:15:27 +0000161 SmallVector<uint64_t, 16> RawMask;
Simon Pilgrim97a48202016-09-29 15:25:48 +0000162 if (!extractConstantMask(C, ElSize, UndefElts, RawMask))
Craig Topper69653af2015-12-31 22:40:45 +0000163 return;
164
Craig Topperc8e183f2018-10-22 22:14:05 +0000165 unsigned NumElts = Width / ElSize;
Simon Pilgrim97a48202016-09-29 15:25:48 +0000166 unsigned NumEltsPerLane = 128 / ElSize;
167 assert((NumElts == 2 || NumElts == 4 || NumElts == 8 || NumElts == 16) &&
Craig Topper69653af2015-12-31 22:40:45 +0000168 "Unexpected number of vector elements.");
Craig Topper69653af2015-12-31 22:40:45 +0000169
Simon Pilgrim97a48202016-09-29 15:25:48 +0000170 for (unsigned i = 0; i != NumElts; ++i) {
171 if (UndefElts[i]) {
Craig Topper69653af2015-12-31 22:40:45 +0000172 ShuffleMask.push_back(SM_SentinelUndef);
173 continue;
174 }
Simon Pilgrim97a48202016-09-29 15:25:48 +0000175
176 int Index = i & ~(NumEltsPerLane - 1);
177 uint64_t Element = RawMask[i];
Craig Topper69653af2015-12-31 22:40:45 +0000178 if (ElSize == 64)
179 Index += (Element >> 1) & 0x1;
180 else
181 Index += Element & 0x3;
Simon Pilgrim97a48202016-09-29 15:25:48 +0000182
Craig Topper69653af2015-12-31 22:40:45 +0000183 ShuffleMask.push_back(Index);
184 }
Craig Topper69653af2015-12-31 22:40:45 +0000185}
186
Simon Pilgrim2ead8612016-06-04 21:44:28 +0000187void DecodeVPERMIL2PMask(const Constant *C, unsigned M2Z, unsigned ElSize,
Craig Topperc8e183f2018-10-22 22:14:05 +0000188 unsigned Width,
Simon Pilgrim2ead8612016-06-04 21:44:28 +0000189 SmallVectorImpl<int> &ShuffleMask) {
190 Type *MaskTy = C->getType();
Simon Pilgrim2ead8612016-06-04 21:44:28 +0000191 unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits();
Douglas Katzman3ace13a2016-09-29 17:26:12 +0000192 (void)MaskTySize;
Craig Topperc8e183f2018-10-22 22:14:05 +0000193 assert((MaskTySize == 128 || MaskTySize == 256) &&
194 Width >= MaskTySize && "Unexpected vector size.");
Simon Pilgrim97a48202016-09-29 15:25:48 +0000195
196 // The shuffle mask requires elements the same size as the target.
Craig Topper53e5a38d2017-02-27 16:15:25 +0000197 APInt UndefElts;
Simon Pilgrim97a48202016-09-29 15:25:48 +0000198 SmallVector<uint64_t, 8> RawMask;
199 if (!extractConstantMask(C, ElSize, UndefElts, RawMask))
Simon Pilgrim2ead8612016-06-04 21:44:28 +0000200 return;
201
Craig Topperc8e183f2018-10-22 22:14:05 +0000202 unsigned NumElts = Width / ElSize;
Simon Pilgrim97a48202016-09-29 15:25:48 +0000203 unsigned NumEltsPerLane = 128 / ElSize;
204 assert((NumElts == 2 || NumElts == 4 || NumElts == 8) &&
Simon Pilgrim2ead8612016-06-04 21:44:28 +0000205 "Unexpected number of vector elements.");
Simon Pilgrim2ead8612016-06-04 21:44:28 +0000206
Simon Pilgrim97a48202016-09-29 15:25:48 +0000207 for (unsigned i = 0; i != NumElts; ++i) {
208 if (UndefElts[i]) {
Simon Pilgrim2ead8612016-06-04 21:44:28 +0000209 ShuffleMask.push_back(SM_SentinelUndef);
210 continue;
211 }
212
213 // VPERMIL2 Operation.
214 // Bits[3] - Match Bit.
215 // Bits[2:1] - (Per Lane) PD Shuffle Mask.
216 // Bits[2:0] - (Per Lane) PS Shuffle Mask.
Simon Pilgrim97a48202016-09-29 15:25:48 +0000217 uint64_t Selector = RawMask[i];
Chandler Carruth4c0e94d2016-06-11 09:13:00 +0000218 unsigned MatchBit = (Selector >> 3) & 0x1;
Simon Pilgrim2ead8612016-06-04 21:44:28 +0000219
220 // M2Z[0:1] MatchBit
221 // 0Xb X Source selected by Selector index.
222 // 10b 0 Source selected by Selector index.
223 // 10b 1 Zero.
224 // 11b 0 Zero.
225 // 11b 1 Source selected by Selector index.
Chandler Carruth306e2702016-06-11 08:02:01 +0000226 if ((M2Z & 0x2) != 0u && MatchBit != (M2Z & 0x1)) {
Simon Pilgrim2ead8612016-06-04 21:44:28 +0000227 ShuffleMask.push_back(SM_SentinelZero);
228 continue;
229 }
230
Simon Pilgrim97a48202016-09-29 15:25:48 +0000231 int Index = i & ~(NumEltsPerLane - 1);
Simon Pilgrim163987a2016-06-05 14:33:43 +0000232 if (ElSize == 64)
233 Index += (Selector >> 1) & 0x1;
234 else
235 Index += Selector & 0x3;
Simon Pilgrim2ead8612016-06-04 21:44:28 +0000236
237 int Src = (Selector >> 2) & 0x1;
Simon Pilgrim97a48202016-09-29 15:25:48 +0000238 Index += Src * NumElts;
Simon Pilgrim2ead8612016-06-04 21:44:28 +0000239 ShuffleMask.push_back(Index);
240 }
Simon Pilgrim2ead8612016-06-04 21:44:28 +0000241}
242
Craig Topperc8e183f2018-10-22 22:14:05 +0000243void DecodeVPPERMMask(const Constant *C, unsigned Width,
244 SmallVectorImpl<int> &ShuffleMask) {
245 Type *MaskTy = C->getType();
246 unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits();
247 (void)MaskTySize;
248 assert(Width == 128 && Width >= MaskTySize && "Unexpected vector size.");
Simon Pilgrim1cc57122016-04-09 14:51:26 +0000249
Simon Pilgrim97a48202016-09-29 15:25:48 +0000250 // The shuffle mask requires a byte vector.
Craig Topper53e5a38d2017-02-27 16:15:25 +0000251 APInt UndefElts;
Craig Toppere1be95c2017-02-27 16:15:27 +0000252 SmallVector<uint64_t, 16> RawMask;
Simon Pilgrim97a48202016-09-29 15:25:48 +0000253 if (!extractConstantMask(C, 8, UndefElts, RawMask))
Simon Pilgrim1cc57122016-04-09 14:51:26 +0000254 return;
255
Craig Topperc8e183f2018-10-22 22:14:05 +0000256 unsigned NumElts = Width / 8;
Simon Pilgrim97a48202016-09-29 15:25:48 +0000257 assert(NumElts == 16 && "Unexpected number of vector elements.");
Simon Pilgrim1cc57122016-04-09 14:51:26 +0000258
Simon Pilgrim97a48202016-09-29 15:25:48 +0000259 for (unsigned i = 0; i != NumElts; ++i) {
260 if (UndefElts[i]) {
261 ShuffleMask.push_back(SM_SentinelUndef);
Simon Pilgrim1cc57122016-04-09 14:51:26 +0000262 continue;
263 }
264
265 // VPPERM Operation
266 // Bits[4:0] - Byte Index (0 - 31)
267 // Bits[7:5] - Permute Operation
268 //
269 // Permute Operation:
270 // 0 - Source byte (no logical operation).
271 // 1 - Invert source byte.
272 // 2 - Bit reverse of source byte.
273 // 3 - Bit reverse of inverted source byte.
274 // 4 - 00h (zero - fill).
275 // 5 - FFh (ones - fill).
276 // 6 - Most significant bit of source byte replicated in all bit positions.
Simon Pilgrim97a48202016-09-29 15:25:48 +0000277 // 7 - Invert most significant bit of source byte and replicate in all bit
278 // positions.
279 uint64_t Element = RawMask[i];
280 uint64_t Index = Element & 0x1F;
281 uint64_t PermuteOp = (Element >> 5) & 0x7;
Simon Pilgrim1cc57122016-04-09 14:51:26 +0000282
Simon Pilgrim97a48202016-09-29 15:25:48 +0000283 if (PermuteOp == 4) {
284 ShuffleMask.push_back(SM_SentinelZero);
285 continue;
Simon Pilgrim1cc57122016-04-09 14:51:26 +0000286 }
Simon Pilgrim97a48202016-09-29 15:25:48 +0000287 if (PermuteOp != 0) {
288 ShuffleMask.clear();
289 return;
290 }
291 ShuffleMask.push_back((int)Index);
Simon Pilgrim1cc57122016-04-09 14:51:26 +0000292 }
Simon Pilgrim1cc57122016-04-09 14:51:26 +0000293}
294
Craig Topperc8e183f2018-10-22 22:14:05 +0000295void DecodeVPERMVMask(const Constant *C, unsigned ElSize, unsigned Width,
Craig Topper69653af2015-12-31 22:40:45 +0000296 SmallVectorImpl<int> &ShuffleMask) {
Craig Topperc8e183f2018-10-22 22:14:05 +0000297 assert((Width == 128 || Width == 256 || Width == 512) &&
298 C->getType()->getPrimitiveSizeInBits() >= Width &&
Craig Topper448358b2016-10-18 04:48:33 +0000299 "Unexpected vector size.");
300 assert((ElSize == 8 || ElSize == 16 || ElSize == 32 || ElSize == 64) &&
301 "Unexpected vector element size.");
302
303 // The shuffle mask requires elements the same size as the target.
Craig Topper53e5a38d2017-02-27 16:15:25 +0000304 APInt UndefElts;
Craig Toppere1be95c2017-02-27 16:15:27 +0000305 SmallVector<uint64_t, 64> RawMask;
Craig Topper448358b2016-10-18 04:48:33 +0000306 if (!extractConstantMask(C, ElSize, UndefElts, RawMask))
307 return;
308
Craig Topperc8e183f2018-10-22 22:14:05 +0000309 unsigned NumElts = Width / ElSize;
Craig Topper448358b2016-10-18 04:48:33 +0000310
311 for (unsigned i = 0; i != NumElts; ++i) {
312 if (UndefElts[i]) {
313 ShuffleMask.push_back(SM_SentinelUndef);
314 continue;
Craig Topper69653af2015-12-31 22:40:45 +0000315 }
Craig Topper448358b2016-10-18 04:48:33 +0000316 int Index = RawMask[i] & (NumElts - 1);
317 ShuffleMask.push_back(Index);
Craig Topper69653af2015-12-31 22:40:45 +0000318 }
Craig Topper69653af2015-12-31 22:40:45 +0000319}
320
Craig Topperc8e183f2018-10-22 22:14:05 +0000321void DecodeVPERMV3Mask(const Constant *C, unsigned ElSize, unsigned Width,
Craig Topper69653af2015-12-31 22:40:45 +0000322 SmallVectorImpl<int> &ShuffleMask) {
Craig Topperc8e183f2018-10-22 22:14:05 +0000323 assert((Width == 128 || Width == 256 || Width == 512) &&
324 C->getType()->getPrimitiveSizeInBits() >= Width &&
Craig Topper7268bf92016-10-18 04:00:32 +0000325 "Unexpected vector size.");
326 assert((ElSize == 8 || ElSize == 16 || ElSize == 32 || ElSize == 64) &&
327 "Unexpected vector element size.");
328
329 // The shuffle mask requires elements the same size as the target.
Craig Topper53e5a38d2017-02-27 16:15:25 +0000330 APInt UndefElts;
Craig Toppere1be95c2017-02-27 16:15:27 +0000331 SmallVector<uint64_t, 64> RawMask;
Craig Topper7268bf92016-10-18 04:00:32 +0000332 if (!extractConstantMask(C, ElSize, UndefElts, RawMask))
333 return;
334
Craig Topperc8e183f2018-10-22 22:14:05 +0000335 unsigned NumElts = Width / ElSize;
Craig Topper7268bf92016-10-18 04:00:32 +0000336
337 for (unsigned i = 0; i != NumElts; ++i) {
338 if (UndefElts[i]) {
339 ShuffleMask.push_back(SM_SentinelUndef);
340 continue;
Craig Topper69653af2015-12-31 22:40:45 +0000341 }
Craig Topper7268bf92016-10-18 04:00:32 +0000342 int Index = RawMask[i] & (NumElts*2 - 1);
343 ShuffleMask.push_back(Index);
Craig Topper69653af2015-12-31 22:40:45 +0000344 }
345}
346} // llvm namespace