<div dir="ltr">I m still unable to solve vshuffle issue. Can you tell me how to split v64i32 shuffle into 4 v16i32 shuffles?<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Apr 11, 2018 at 12:14 AM, hameeza ahmed <span dir="ltr"><<a href="mailto:hahmed2305@gmail.com" target="_blank">hahmed2305@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5"><div dir="ltr"><div class="gmail_quote"><div dir="ltr"><div>Please tell me whether the following implementation is correct.....<br>My target supports 64 bit mask means immediate(0-2^63)<br><br></div>I
 have implemented it but i dont know whether its correct or not. Please 
see the changes below that i have made in x86isellowering.cpp<br><br>static SDValue lower2048BitVectorShuffle(cons<wbr>t SDLoc &DL, ArrayRef<int> Mask,<br>                              <wbr>          MVT VT, SDValue V1, SDValue V2,<br>                              <wbr>          const SmallBitVector &Zeroable,<br>                              <wbr>          const X86Subtarget &Subtarget,<br>                              <wbr>          SelectionDAG &DAG) {<br><br><br>  // If we have a single input to the zero element, insert that into V1 if we<br>  // can do so cheaply.<br>  int NumElts = Mask.size();<br>  int NumV2Elements = count_if(Mask, [NumElts](int M) { return M >= NumElts; });<br><br>  if (NumV2Elements == 1 && Mask[0] >= NumElts)<br>    if (SDValue Insertion = lowerVectorShuffleAsElementIns<wbr>ertion(<br>            DL, VT, V1, V2, Mask, Zeroable, Subtarget, DAG))<br>      return Insertion;<br><br>  // Check for being able to broadcast a single element.<br>  if (SDValue Broadcast =<br>          lowerVectorShuffleAsBroadcast(<wbr>DL, VT, V1, V2, Mask, Subtarget, DAG))<br>    return Broadcast;<br><br>  // Dispatch to each element type for lowering. If we don't have support for<br>  // specific element type shuffles at 512 bits, immediately split them and<br>  // lower them. Each lowering routine of a given type is allowed to assume that<br>  // the requisite ISA extensions for that element type are available.<br>  switch (VT.SimpleTy) {<br>  case MVT::v32f64:<br>    return lowerV32F64VectorShuffle(DL, Mask, Zeroable, V1, V2, Subtarget, DAG);<br>  case MVT::v64f32:<br>    return lowerV64F32VectorShuffle(DL, Mask, Zeroable, V1, V2, Subtarget, DAG);<br>  case MVT::v32i64:<br>    return lowerV32I64VectorShuffle(DL, Mask, Zeroable, V1, V2, Subtarget, DAG);<br>  case MVT::v64i32:<br>    return lowerV64I32VectorShuffle(DL, Mask, Zeroable, V1, V2, Subtarget, DAG);<br><br>  default:<br>    llvm_unreachable("Not a valid P x86 vector type!");<br>  }<br>}<br><br>static SDValue lowerV64I32VectorShuffle(const SDLoc &DL, ArrayRef<int> Mask,<br>                              <wbr>          const SmallBitVector &Zeroable,<br>                              <wbr>          SDValue V1, SDValue V2,<br>                              <wbr>          const X86Subtarget &Subtarget,<br>                              <wbr>          SelectionDAG &DAG) {<br><br> assert(V1.getSimpleValueType(<wbr>) == MVT::v64i32 && "Bad operand type!");<br>  assert(V2.getSimpleValueType() == MVT::v64i32 && "Bad operand type!");<br>  assert(Mask.size() == 64 && "Unexpected mask size for v64 shuffle!");<br>  <br>  if (SDValue ZExt = lowerVectorShuffleAsZeroOrAnyE<wbr>xtend(<br>          DL, MVT::v64i32, V1, V2, Mask, Zeroable, Subtarget, DAG))<br>    return ZExt;<br> <br>    <br>      SmallVector<int, 16> RepeatedMask;<br><br>  bool Is128BitLaneRepeatedShuffle =<br>      is128BitLaneRepeatedShuffleMas<wbr>k(MVT::v64i32, Mask, RepeatedMask);<br><br>  if (Is128BitLaneRepeatedShuffle) {<br>  //  assert(RepeatedMask.size() == 16 && "Unexpected repeated mask size!");<br>  <br><br>   if (V2.isUndef())<br>     { <br>return DAG.getNode(X86ISD::PSHUFD_P64<wbr>, DL, MVT::v64i32, V1,<br>                         getV16X86ShuffleImm64ForMask(/<wbr>*Repeated*/Mask, DL, DAG));<br><br><br>}<br><br>    // Use dedicated unpack instructions for masks that match their pattern.<br>    if (SDValue V =<br>            lowerVectorShuffleWithUNPCK(DL<wbr>, MVT::v64i32, Mask, V1, V2, DAG))<br>      return V;<br>  }<br> <br>  <br><br>  // Try to use shift instructions.<br>  if (SDValue Shift = lowerVectorShuffleAsShift(DL, MVT::v64i32, V1, V2, Mask,<br>                              <wbr>                  Zeroable, Subtarget, DAG))<br>    return Shift;<br><br>  // Try to use VALIGN.<br>  if (SDValue Rotate = lowerVectorShuffleAsRotate(DL, MVT::v64i32, V1, V2,<br>                              <wbr>                    Mask, Subtarget, DAG))<br>    return Rotate;<br><br>  // Assume that a single SHUFPS is faster than using a permv shuffle.<br>  // If some CPU is harmed by the domain switch, we can fix it in a later pass.<br> <br>  // If we have AVX512F support, we can use VEXPAND.<br>  if (SDValue V = lowerVectorShuffleToEXPAND(DL, MVT::v64i32, Zeroable, Mask,<br>                              <wbr>               V1, V2, DAG, Subtarget))<br>    return V;<br><br>  return lowerVectorShuffleWithPERMV(DL<wbr>, MVT::v64i32, Mask, V1, V2, DAG);<br><br>}<br><br>static SDValue lowerV32I64VectorShuffle(const SDLoc &DL, ArrayRef<int> Mask,<br>                              <wbr>         const SmallBitVector &Zeroable,<br>                              <wbr>         SDValue V1, SDValue V2,<br>                              <wbr>         const X86Subtarget &Subtarget,<br>                              <wbr>         SelectionDAG &DAG) {<br>  assert(V1.getSimpleValueType() == MVT::v32i64 && "Bad operand type!");<br>  assert(V2.getSimpleValueType() == MVT::v32i64 && "Bad operand type!");<br>  assert(Mask.size() == 32 && "Unexpected mask size for v8 shuffle!");<br><br>  if (SDValue Shuf128 =<br>          lowerV16X128VectorShuffle(DL, MVT::v32i64, Mask, V1, V2, DAG))<br>    return Shuf128;<br><br>  if (V2.isUndef()) {<br>    // When the shuffle is mirrored between the 128-bit lanes of the unit, we<br>    // can use lower latency instructions that will operate on all four<br>    // 128-bit lanes.<br>    SmallVector<int, 8> Repeated128Mask;<br>    if (is128BitLaneRepeatedShuffleMa<wbr>sk(MVT::v32i64, Mask, Repeated128Mask)) {<br>      SmallVector<int, 64> PSHUFDMask;<br>      scaleShuffleMask(8, Repeated128Mask, PSHUFDMask);<br>      return DAG.getBitcast(<br>          MVT::v32i64,<br>          DAG.getNode(X86ISD::PSHUFD_P64<wbr>, DL, MVT::v64i32,<br>                      DAG.getBitcast(MVT::v64i32, V1),<br>                      getV16X86ShuffleImm64ForMask(P<wbr>SHUFDMask, DL, DAG)));<br>    }<br><br>    SmallVector<int, 16> Repeated256Mask;<br>    if (is256BitLaneRepeatedShuffleMa<wbr>sk(MVT::v32i64, Mask, Repeated256Mask))<br>      return DAG.getNode(X86ISD::VPERMI, DL, MVT::v32i64, V1,<br>                         getV16X86ShuffleImm64ForMask(R<wbr>epeated256Mask, DL, DAG));<br>  }<br><br>  // Try to use shift instructions.<br>  if (SDValue Shift = lowerVectorShuffleAsShift(DL, MVT::v32i64, V1, V2, Mask,<br>                              <wbr>                  Zeroable, Subtarget, DAG))<br>    return Shift;<br><br>  // Try to use VALIGN.<br>  if (SDValue Rotate = lowerVectorShuffleAsRotate(DL, MVT::v32i64, V1, V2,<br>                              <wbr>                    Mask, Subtarget, DAG))<br>    return Rotate;<br><br>  // Try to use PALIGNR.<br>  if (SDValue Rotate = lowerVectorShuffleAsByteRotate<wbr>(DL, MVT::v32i64, V1, V2,<br>                              <wbr>                        Mask, Subtarget, DAG))<br>    return Rotate;<br><br>  if (SDValue Unpck =<br>          lowerVectorShuffleWithUNPCK(DL<wbr>, MVT::v32i64, Mask, V1, V2, DAG))<br>    return Unpck;<br>  // If we have AVX512F support, we can use VEXPAND.<br>  if (SDValue V = lowerVectorShuffleToEXPAND(DL, MVT::v32i64, Zeroable, Mask, V1,<br>                              <wbr>               V2, DAG, Subtarget))<br>    return V;<br><br>  return lowerVectorShuffleWithPERMV(DL<wbr>, MVT::v32i64, Mask, V1, V2, DAG);<br>}<br><br>static SDValue getV64X86ShuffleImm64ForMask(A<wbr>rrayRef<int> Mask, SDLoc DL,<br><div><div><div><div class="gmail_extra">                              <wbr>            SelectionDAG &DAG) {<br>  return DAG.getConstant(getV64X86Shuff<wbr>leImm(Mask), DL, MVT::i64);<br>}<br><br><br>static uint64_t getV16X86ShuffleImm(ArrayRef<i<wbr>nt> Mask) {<br> // assert(Mask.size() == 16 && "Only 16-lane shuffle masks");<br>  assert(Mask[0] >= -1 && Mask[0] < 16 && "Out of bound mask element!");<br>  assert(Mask[1] >= -1 && Mask[1] < 16 && "Out of bound mask element!");<br>  assert(Mask[2] >= -1 && Mask[2] < 16 && "Out of bound mask element!");<br>  assert(Mask[3] >= -1 && Mask[3] < 16 && "Out of bound mask element!");<br>  assert(Mask[4] >= -1 && Mask[4] < 16 && "Out of bound mask element!");<br>  assert(Mask[5] >= -1 && Mask[5] < 16 && "Out of bound mask element!");<br>  assert(Mask[6] >= -1 && Mask[6] < 16 && "Out of bound mask element!");<br>  assert(Mask[7] >= -1 && Mask[7] < 16 && "Out of bound mask element!");<br>  assert(Mask[8] >= -1 && Mask[8] < 16 && "Out of bound mask element!");<br>  assert(Mask[9] >= -1 && Mask[9] < 16 && "Out of bound mask element!");<br>  assert(Mask[10] >= -1 && Mask[10] < 16 && "Out of bound mask element!");<br>  assert(Mask[11] >= -1 && Mask[11] < 16 && "Out of bound mask element!");<br>  assert(Mask[12] >= -1 && Mask[12] < 16 && "Out of bound mask element!");<br>  assert(Mask[13] >= -1 && Mask[13] < 16 && "Out of bound mask element!");<br>  assert(Mask[14] >= -1 && Mask[14] < 16 && "Out of bound mask element!");<br>  assert(Mask[15] >= -1 && Mask[15] < 16 && "Out of bound mask element!");<br>  <br>  uint64_t Imm = 0;<br>  Imm |= (Mask[0] < 0 ? 0 : Mask[0]) << 0;<br>  Imm |= (Mask[1] < 0 ? 1 : Mask[1]) << 2;<br>  Imm |= (Mask[2] < 0 ? 2 : Mask[2]) << 4;<br>  Imm |= (Mask[3] < 0 ? 3 : Mask[3]) << 6;<br>  Imm |= (Mask[4] < 0 ? 4 : Mask[4]) << 8;<br>  Imm |= (Mask[5] < 0 ? 5 : Mask[5]) << 10;<br>  Imm |= (Mask[6] < 0 ? 6 : Mask[6]) << 12;<br>  Imm |= (Mask[7] < 0 ? 7 : Mask[7]) << 14;<br>   Imm |= (Mask[8] < 0 ? 8 : Mask[8]) << 16;<br>  Imm |= (Mask[9] < 0 ? 9 : Mask[9]) << 18;<br>  Imm |= (Mask[10] < 0 ? 10 : Mask[10]) << 20;<br>  Imm |= (Mask[11] < 0 ? 11 : Mask[11]) << 22;<br>   Imm |= (Mask[12] < 0 ? 12 : Mask[12]) << 24;<br>  Imm |= (Mask[13] < 0 ? 13 : Mask[13]) << 26;<br>  Imm |= (Mask[14] < 0 ? 14 : Mask[14]) << 28;<br>  Imm |= (Mask[15] < 0 ? 15 : Mask[15]) << 30;<br>  <br>  return Imm;<br>}<br><br><br>static SDValue lowerV16X128VectorShuffle(cons<wbr>t SDLoc &DL, MVT VT,<br>                              <wbr>          ArrayRef<int> Mask, SDValue V1,<br>                              <wbr>          SDValue V2, SelectionDAG &DAG) {<br>  assert(VT.getScalarSizeInBits(<wbr>) == 64 &&<br>         "Unexpected element type size for 128bit shuffle.");<br><br>  // To handle 256 bit vector requires VLX and most probably<br>  // function lowerV2X128VectorShuffle() is better solution.<br>  assert(VT.is2048BitVector() && "Unexpected vector size for 2048bit shuffle.");<br><br>  SmallVector<int, 16> WidenedMask;<br>  if (!canWidenShuffleElements(Mask<wbr>, WidenedMask))<br>    return SDValue();<br><br>  // Check for patterns which can be matched with a single insert of a 256-bit<br>  // subvector.<br>  bool OnlyUsesV1 = isShuffleEquivalent(V1, V2, Mask,<br>                              <wbr>          {0, 1, 2, 3, 4, 5, 6, 7,0, 1, 2, 3, 4, 5, 6, 7});<br>  if (OnlyUsesV1 || isShuffleEquivalent(V1, V2, Mask,<br>                              <wbr>          {0, 1, 2, 3, 4, 5, 6, 7, 12, 13, 14, 15,16,17,18,19})) <br><br> {<br>    MVT SubVT = MVT::getVectorVT(VT.getVectorE<wbr>lementType(), 16);<br>    SDValue LoV = DAG.getNode(ISD::EXTRACT_SUBVE<wbr>CTOR, DL, SubVT, V1,<br>                              DAG.getIntPtrConstant(0, DL));<br>    SDValue HiV = DAG.getNode(ISD::EXTRACT_SUBVE<wbr>CTOR, DL, SubVT,<br>                              OnlyUsesV1 ? V1 : V2,<br>                              DAG.getIntPtrConstant(0, DL));<br>    return DAG.getNode(ISD::CONCAT_VECTOR<wbr>S, DL, VT, LoV, HiV);<br>  }<br><br>  assert(WidenedMask.size() == 16);<br><br>  // See if this is an insertion of the lower 128-bits of V2 into V1.<br>  bool IsInsert = true;<br>  int V2Index = -1;<br>  for (int i = 0; i < 16; ++i) {<br>    assert(WidenedMask[i] >= -1);<br>    if (WidenedMask[i] < 0)<br>      continue;<br><br>    // Make sure all V1 subvectors are in place.<br>    if (WidenedMask[i] < 16) {<br>      if (WidenedMask[i] != i) {<br>        IsInsert = false;<br>        break;<br>      }<br>    } else {<br>      // Make sure we only have a single V2 index and its the lowest 128-bits.<br>      if (V2Index >= 0 || WidenedMask[i] != 16) {<br>        IsInsert = false;<br>        break;<br>      }<br>      V2Index = i;<br>    }<br>  }<br>  if (IsInsert && V2Index >= 0) {<br>    MVT SubVT = MVT::getVectorVT(VT.getVectorE<wbr>lementType(), 2);<br>    SDValue Subvec = DAG.getNode(ISD::EXTRACT_SUBVE<wbr>CTOR, DL, SubVT, V2,<br>                              <wbr>   DAG.getIntPtrConstant(0, DL));<br>    return insert128BitVector(V1, Subvec, V2Index * 2, DAG, DL);<br>  }<br><br>  // Try to lower to to vshuf64x2/vshuf32x4.<br> 
 SDValue Ops[8] = {DAG.getUNDEF(VT), DAG.getUNDEF(VT), DAG.getUNDEF(VT),
 DAG.getUNDEF(VT), DAG.getUNDEF(VT), DAG.getUNDEF(VT), DAG.getUNDEF(VT),
 DAG.getUNDEF(VT)};<br>  unsigned PermMask = 0;<br>  // Insure elements came from the same Op.<br>  for (int i = 0; i < 16; ++i) {<br>    assert(WidenedMask[i] >= -1);<br>    if (WidenedMask[i] < 0)<br>      continue;<br><br>    SDValue Op = WidenedMask[i] >= 16 ? V2 : V1;<br>    unsigned OpIndex = i / 2;<br>    if (Ops[OpIndex].isUndef())<br>      Ops[OpIndex] = Op;<br>    else if (Ops[OpIndex] != Op)<br>      return SDValue();<br><br>    // Convert the 128-bit shuffle mask selection values into 128-bit selection<br>    // bits defined by a vshuf64x2 instruction's immediate control byte.<br>    PermMask |= (WidenedMask[i] % 16) << (i * 2);<br>  }<br><br>  return DAG.getNode(X86ISD::SHUF128_P6<wbr>4, DL, VT, Ops[0], Ops[1],<br>                     DAG.getConstant(PermMask, DL, MVT::i64));<br>}<br><br><br><br></div><div class="gmail_extra">Please help...i m really sorry for asking but i m stuck here..The code runs w/o error at the o/p it gives following assembly;<br><br>    P_256B_VSHUF64x2_QWORD    R_0_R2048b_0, R_0_R2048b_1, R_0_R2048b_1, 236 # encoding: []<br>    P_256B_VADD_DWORD    R_0_R2048b_1, R_0_R2048b_1, R_0_R2048b_0 # encoding: [0x61,0x02,0x46,0x00,0x00,0x20<wbr>,0x00,0x04,0x00,0x00,0x00]<br>    P_256B_VSHUF64x2_QWORD    R_0_R2048b_0, R_0_R2048b_1, R_0_R2048b_1, 244 # encoding: []<br>    P_256B_VADD_DWORD    R_0_R2048b_1, R_0_R2048b_1, R_0_R2048b_0 # encoding: [0x61,0x02,0x46,0x00,0x00,0x20<wbr>,0x00,0x04,0x00,0x00,0x00]<br>    P_256B_VSHUF64x2_QWORD    R_0_R2048b_0, R_0_R2048b_1, R_0_R2048b_0, 14 # encoding: []<br>    P_256B_VADD_DWORD    R_0_R2048b_1, R_0_R2048b_1, R_0_R2048b_0 # encoding: [0x61,0x02,0x46,0x00,0x00,0x20<wbr>,0x00,0x04,0x00,0x00,0x00]<br>    P_256B_VSHUF64x2_QWORD    R_0_R2048b_0, R_0_R2048b_1, R_0_R2048b_0, 1 # encoding: []<br>    P_256B_VADD_DWORD    R_0_R2048b_1, R_0_R2048b_1, R_0_R2048b_0 # encoding: [0x61,0x02,0x46,0x00,0x00,0x20<wbr>,0x00,0x04,0x00,0x00,0x00]<br>    P_256B_PSHUFFLE_DWORD    R_0_R2048b_0, R_0_R2048b_1, 236 # encoding: []<br>    P_256B_VADD_DWORD    R_0_R2048b_1, R_0_R2048b_1, R_0_R2048b_0 # encoding: [0x61,0x02,0x46,0x00,0x00,0x20<wbr>,0x00,0x04,0x00,0x00,0x00]<br>    P_256B_PSHUFFLE_DWORD    R_0_R2048b_0, R_0_R2048b_1, 229 # encoding: []<br><br></div><div class="gmail_extra">Here the imm are small (0-255) looks like 8 bits....<br></div><div class="gmail_extra">What to do? Please help....<div class="m_-8813735244155132044m_-4245611836209439424gmail-yj6qo m_-8813735244155132044m_-4245611836209439424gmail-ajU"><div id="m_-8813735244155132044m_-4245611836209439424gmail-:1my" class="m_-8813735244155132044m_-4245611836209439424gmail-ajR"><img class="m_-8813735244155132044m_-4245611836209439424gmail-ajT" src="https://ssl.gstatic.com/ui/v1/icons/mail/images/cleardot.gif"></div></div></div></div></div></div><br><br><br><div class="gmail_extra"><div class="gmail_quote"><br></div></div></div></div></div>
</div></div></blockquote></div><br></div>