llvm.org GIT mirror llvm / 061feda
[CodeGen] Make the code that detects a if a shuffle is really a concatenation of the inputs more general purpose. We can now handle concatenation of each source multiple times. The previous code just checked for each source to appear once in either order. This also now handles an entire source vector sized piece having undef indices correctly. We now concat with UNDEF instead of using one of the sources. This is responsible for the test case change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@274483 91177308-0d34-0410-b5e6-96231b3b80d8 Craig Topper 4 years ago
2 changed file(s) with 41 addition(s) and 39 deletion(s). Raw diff Collapse all Expand all
29952995 InVec, InIdx));
29962996 }
29972997
2998 // Utility for visitShuffleVector - Return true if every element in Mask,
2999 // beginning from position Pos and ending in Pos+Size, falls within the
3000 // specified sequential range [L, L+Pos). or is undef.
3001 static bool isSequentialInRange(const SmallVectorImpl &Mask,
3002 unsigned Pos, unsigned Size, int Low) {
3003 for (unsigned i = Pos, e = Pos+Size; i != e; ++i, ++Low)
3004 if (Mask[i] >= 0 && Mask[i] != Low)
3005 return false;
3006 return true;
3007 }
3008
30092998 void SelectionDAGBuilder::visitShuffleVector(const User &I) {
30102999 SDValue Src1 = getValue(I.getOperand(0));
30113000 SDValue Src2 = getValue(I.getOperand(1));
30293018 // Mask is longer than the source vectors and is a multiple of the source
30303019 // vectors. We can use concatenate vector to make the mask and vectors
30313020 // lengths match.
3032 if (SrcNumElts*2 == MaskNumElts) {
3033 // First check for Src1 in low and Src2 in high
3034 if (isSequentialInRange(Mask, 0, SrcNumElts, 0) &&
3035 isSequentialInRange(Mask, SrcNumElts, SrcNumElts, SrcNumElts)) {
3036 // The shuffle is concatenating two vectors together.
3037 setValue(&I, DAG.getNode(ISD::CONCAT_VECTORS, getCurSDLoc(),
3038 VT, Src1, Src2));
3039 return;
3021
3022 unsigned NumConcat = MaskNumElts / SrcNumElts;
3023
3024 // Check if the shuffle is some kind of concatenation of the input vectors.
3025 bool IsConcat = true;
3026 SmallVector ConcatSrcs(NumConcat, -1);
3027 for (unsigned i = 0; i != MaskNumElts; ++i) {
3028 int Idx = Mask[i];
3029 if (Idx < 0)
3030 continue;
3031 // Ensure the indices in each SrcVT sized piece are sequential and that
3032 // the same source is used for the whole piece.
3033 if ((Idx % SrcNumElts != (i % SrcNumElts)) ||
3034 (ConcatSrcs[i / SrcNumElts] >= 0 &&
3035 ConcatSrcs[i / SrcNumElts] != (int)(Idx / SrcNumElts))) {
3036 IsConcat = false;
3037 break;
30403038 }
3041 // Then check for Src2 in low and Src1 in high
3042 if (isSequentialInRange(Mask, 0, SrcNumElts, SrcNumElts) &&
3043 isSequentialInRange(Mask, SrcNumElts, SrcNumElts, 0)) {
3044 // The shuffle is concatenating two vectors together.
3045 setValue(&I, DAG.getNode(ISD::CONCAT_VECTORS, getCurSDLoc(),
3046 VT, Src2, Src1));
3047 return;
3039 // Remember which source this index came from.
3040 ConcatSrcs[i / SrcNumElts] = Idx / SrcNumElts;
3041 }
3042
3043 // The shuffle is concatenating multiple vectors together. Just emit
3044 // a CONCAT_VECTORS operation.
3045 if (IsConcat) {
3046 SmallVector ConcatOps;
3047 for (auto Src : ConcatSrcs) {
3048 if (Src < 0)
3049 ConcatOps.push_back(DAG.getUNDEF(SrcVT));
3050 else if (Src == 0)
3051 ConcatOps.push_back(Src1);
3052 else
3053 ConcatOps.push_back(Src2);
30483054 }
3055 setValue(&I, DAG.getNode(ISD::CONCAT_VECTORS, getCurSDLoc(),
3056 VT, ConcatOps));
3057 return;
30493058 }
30503059
30513060 // Pad both vectors with undefs to make them the same length as the mask.
3052 unsigned NumConcat = MaskNumElts / SrcNumElts;
3053 bool Src1U = Src1.isUndef();
3054 bool Src2U = Src2.isUndef();
30553061 SDValue UndefVal = DAG.getUNDEF(SrcVT);
30563062
30573063 SmallVector MOps1(NumConcat, UndefVal);
30593065 MOps1[0] = Src1;
30603066 MOps2[0] = Src2;
30613067
3062 Src1 = Src1U ? DAG.getUNDEF(VT) : DAG.getNode(ISD::CONCAT_VECTORS,
3063 getCurSDLoc(), VT, MOps1);
3064 Src2 = Src2U ? DAG.getUNDEF(VT) : DAG.getNode(ISD::CONCAT_VECTORS,
3065 getCurSDLoc(), VT, MOps2);
3068 Src1 = Src1.isUndef() ? DAG.getUNDEF(VT)
3069 : DAG.getNode(ISD::CONCAT_VECTORS,
3070 getCurSDLoc(), VT, MOps1);
3071 Src2 = Src2.isUndef() ? DAG.getUNDEF(VT)
3072 : DAG.getNode(ISD::CONCAT_VECTORS,
3073 getCurSDLoc(), VT, MOps2);
30663074
30673075 // Readjust mask for new input vector length.
30683076 SmallVector MappedOps;
317317 define <4 x double> @test_mm256_castpd128_pd256(<2 x double> %a0) nounwind {
318318 ; X32-LABEL: test_mm256_castpd128_pd256:
319319 ; X32: # BB#0:
320 ; X32-NEXT: vinsertf128 $1, %xmm0, %ymm0, %ymm0
321320 ; X32-NEXT: retl
322321 ;
323322 ; X64-LABEL: test_mm256_castpd128_pd256:
324323 ; X64: # BB#0:
325 ; X64-NEXT: vinsertf128 $1, %xmm0, %ymm0, %ymm0
326324 ; X64-NEXT: retq
327325 %res = shufflevector <2 x double> %a0, <2 x double> %a0, <4 x i32>
328326 ret <4 x double> %res
369367 define <8 x float> @test_mm256_castps128_ps256(<4 x float> %a0) nounwind {
370368 ; X32-LABEL: test_mm256_castps128_ps256:
371369 ; X32: # BB#0:
372 ; X32-NEXT: vinsertf128 $1, %xmm0, %ymm0, %ymm0
373370 ; X32-NEXT: retl
374371 ;
375372 ; X64-LABEL: test_mm256_castps128_ps256:
376373 ; X64: # BB#0:
377 ; X64-NEXT: vinsertf128 $1, %xmm0, %ymm0, %ymm0
378374 ; X64-NEXT: retq
379375 %res = shufflevector <4 x float> %a0, <4 x float> %a0, <8 x i32>
380376 ret <8 x float> %res
397393 define <4 x i64> @test_mm256_castsi128_si256(<2 x i64> %a0) nounwind {
398394 ; X32-LABEL: test_mm256_castsi128_si256:
399395 ; X32: # BB#0:
400 ; X32-NEXT: vinsertf128 $1, %xmm0, %ymm0, %ymm0
401396 ; X32-NEXT: retl
402397 ;
403398 ; X64-LABEL: test_mm256_castsi128_si256:
404399 ; X64: # BB#0:
405 ; X64-NEXT: vinsertf128 $1, %xmm0, %ymm0, %ymm0
406400 ; X64-NEXT: retq
407401 %res = shufflevector <2 x i64> %a0, <2 x i64> %a0, <4 x i32>
408402 ret <4 x i64> %res