1 //===-- X86ShuffleDecode.cpp - X86 shuffle decode logic -------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Define several functions to decode x86 specific shuffle semantics into a
11 // generic vector mask.
13 //===----------------------------------------------------------------------===//
15 #include "X86ShuffleDecode.h"
17 //===----------------------------------------------------------------------===//
18 // Vector Mask Decoding
19 //===----------------------------------------------------------------------===//
23 void DecodeINSERTPSMask(unsigned Imm, SmallVectorImpl<int> &ShuffleMask) {
24 // Defaults the copying the dest value.
25 ShuffleMask.push_back(0);
26 ShuffleMask.push_back(1);
27 ShuffleMask.push_back(2);
28 ShuffleMask.push_back(3);
30 // Decode the immediate.
31 unsigned ZMask = Imm & 15;
32 unsigned CountD = (Imm >> 4) & 3;
33 unsigned CountS = (Imm >> 6) & 3;
35 // CountS selects which input element to use.
36 unsigned InVal = 4+CountS;
37 // CountD specifies which element of destination to update.
38 ShuffleMask[CountD] = InVal;
39 // ZMask zaps values, potentially overriding the CountD elt.
40 if (ZMask & 1) ShuffleMask[0] = SM_SentinelZero;
41 if (ZMask & 2) ShuffleMask[1] = SM_SentinelZero;
42 if (ZMask & 4) ShuffleMask[2] = SM_SentinelZero;
43 if (ZMask & 8) ShuffleMask[3] = SM_SentinelZero;
47 void DecodeMOVHLPSMask(unsigned NElts, SmallVectorImpl<int> &ShuffleMask) {
48 for (unsigned i = NElts/2; i != NElts; ++i)
49 ShuffleMask.push_back(NElts+i);
51 for (unsigned i = NElts/2; i != NElts; ++i)
52 ShuffleMask.push_back(i);
56 void DecodeMOVLHPSMask(unsigned NElts, SmallVectorImpl<int> &ShuffleMask) {
57 for (unsigned i = 0; i != NElts/2; ++i)
58 ShuffleMask.push_back(i);
60 for (unsigned i = 0; i != NElts/2; ++i)
61 ShuffleMask.push_back(NElts+i);
64 /// DecodePSHUFMask - This decodes the shuffle masks for pshufd, and vpermilp*.
65 /// VT indicates the type of the vector allowing it to handle different
66 /// datatypes and vector widths.
67 void DecodePSHUFMask(EVT VT, unsigned Imm, SmallVectorImpl<int> &ShuffleMask) {
68 unsigned NumElts = VT.getVectorNumElements();
70 unsigned NumLanes = VT.getSizeInBits() / 128;
71 unsigned NumLaneElts = NumElts / NumLanes;
74 for (unsigned l = 0; l != NumElts; l += NumLaneElts) {
75 for (unsigned i = 0; i != NumLaneElts; ++i) {
76 ShuffleMask.push_back(NewImm % NumLaneElts + l);
77 NewImm /= NumLaneElts;
79 if (NumLaneElts == 4) NewImm = Imm; // reload imm
83 void DecodePSHUFHWMask(unsigned Imm, SmallVectorImpl<int> &ShuffleMask) {
84 ShuffleMask.push_back(0);
85 ShuffleMask.push_back(1);
86 ShuffleMask.push_back(2);
87 ShuffleMask.push_back(3);
88 for (unsigned i = 0; i != 4; ++i) {
89 ShuffleMask.push_back(4+(Imm & 3));
94 void DecodePSHUFLWMask(unsigned Imm, SmallVectorImpl<int> &ShuffleMask) {
95 for (unsigned i = 0; i != 4; ++i) {
96 ShuffleMask.push_back((Imm & 3));
99 ShuffleMask.push_back(4);
100 ShuffleMask.push_back(5);
101 ShuffleMask.push_back(6);
102 ShuffleMask.push_back(7);
105 /// DecodeSHUFPMask - This decodes the shuffle masks for shufp*. VT indicates
106 /// the type of the vector allowing it to handle different datatypes and vector
108 void DecodeSHUFPMask(EVT VT, unsigned Imm, SmallVectorImpl<int> &ShuffleMask) {
109 unsigned NumElts = VT.getVectorNumElements();
111 unsigned NumLanes = VT.getSizeInBits() / 128;
112 unsigned NumLaneElts = NumElts / NumLanes;
115 for (unsigned l = 0; l != NumElts; l += NumLaneElts) {
116 // Part that reads from dest.
117 for (unsigned i = 0; i != NumLaneElts/2; ++i) {
118 ShuffleMask.push_back(NewImm % NumLaneElts + l);
119 NewImm /= NumLaneElts;
121 // Part that reads from src.
122 for (unsigned i = 0; i != NumLaneElts/2; ++i) {
123 ShuffleMask.push_back(NewImm % NumLaneElts + NumElts + l);
124 NewImm /= NumLaneElts;
126 if (NumLaneElts == 4) NewImm = Imm; // reload imm
130 /// DecodeUNPCKHMask - This decodes the shuffle masks for unpckhps/unpckhpd
131 /// and punpckh*. VT indicates the type of the vector allowing it to handle
132 /// different datatypes and vector widths.
133 void DecodeUNPCKHMask(EVT VT, SmallVectorImpl<int> &ShuffleMask) {
134 unsigned NumElts = VT.getVectorNumElements();
136 // Handle 128 and 256-bit vector lengths. AVX defines UNPCK* to operate
137 // independently on 128-bit lanes.
138 unsigned NumLanes = VT.getSizeInBits() / 128;
139 if (NumLanes == 0 ) NumLanes = 1; // Handle MMX
140 unsigned NumLaneElts = NumElts / NumLanes;
142 for (unsigned l = 0; l != NumElts; l += NumLaneElts) {
143 for (unsigned i = l + NumLaneElts/2, e = l + NumLaneElts; i != e; ++i) {
144 ShuffleMask.push_back(i); // Reads from dest/src1
145 ShuffleMask.push_back(i+NumElts); // Reads from src/src2
150 /// DecodeUNPCKLMask - This decodes the shuffle masks for unpcklps/unpcklpd
151 /// and punpckl*. VT indicates the type of the vector allowing it to handle
152 /// different datatypes and vector widths.
153 void DecodeUNPCKLMask(EVT VT, SmallVectorImpl<int> &ShuffleMask) {
154 unsigned NumElts = VT.getVectorNumElements();
156 // Handle 128 and 256-bit vector lengths. AVX defines UNPCK* to operate
157 // independently on 128-bit lanes.
158 unsigned NumLanes = VT.getSizeInBits() / 128;
159 if (NumLanes == 0 ) NumLanes = 1; // Handle MMX
160 unsigned NumLaneElts = NumElts / NumLanes;
162 for (unsigned l = 0; l != NumElts; l += NumLaneElts) {
163 for (unsigned i = l, e = l + NumLaneElts/2; i != e; ++i) {
164 ShuffleMask.push_back(i); // Reads from dest/src1
165 ShuffleMask.push_back(i+NumElts); // Reads from src/src2
170 void DecodeVPERM2X128Mask(EVT VT, unsigned Imm,
171 SmallVectorImpl<int> &ShuffleMask) {
172 unsigned HalfSize = VT.getVectorNumElements()/2;
173 unsigned FstHalfBegin = (Imm & 0x3) * HalfSize;
174 unsigned SndHalfBegin = ((Imm >> 4) & 0x3) * HalfSize;
176 for (int i = FstHalfBegin, e = FstHalfBegin+HalfSize; i != e; ++i)
177 ShuffleMask.push_back(i);
178 for (int i = SndHalfBegin, e = SndHalfBegin+HalfSize; i != e; ++i)
179 ShuffleMask.push_back(i);