Skip to content

Commit ce81827

Browse files
committedOct 21, 2011
Extend instcombine's shufflevector simplification to handle more cases where the input and output vectors have different sizes. Patch by Xiaoyi Guo.
llvm-svn: 142671
1 parent 2f2e3c4 commit ce81827

File tree

2 files changed

+241
-61
lines changed

2 files changed

+241
-61
lines changed
 

‎llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp

+195-61
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ static bool CheapToScalarize(Value *V, bool isConstant) {
5555

5656
/// getShuffleMask - Read and decode a shufflevector mask.
5757
/// Turn undef elements into negative values.
58-
static std::vector<int> getShuffleMask(const ShuffleVectorInst *SVI) {
58+
static SmallVector<int, 16> getShuffleMask(const ShuffleVectorInst *SVI) {
5959
unsigned NElts = SVI->getType()->getNumElements();
6060
if (isa<ConstantAggregateZero>(SVI->getOperand(2)))
61-
return std::vector<int>(NElts, 0);
61+
return SmallVector<int, 16>(NElts, 0);
6262
if (isa<UndefValue>(SVI->getOperand(2)))
63-
return std::vector<int>(NElts, -1);
63+
return SmallVector<int, 16>(NElts, -1);
6464

65-
std::vector<int> Result;
65+
SmallVector<int, 16> Result;
6666
const ConstantVector *CP = cast<ConstantVector>(SVI->getOperand(2));
6767
for (User::const_op_iterator i = CP->op_begin(), e = CP->op_end(); i!=e; ++i)
6868
if (isa<UndefValue>(*i))
@@ -447,7 +447,7 @@ Instruction *InstCombiner::visitInsertElementInst(InsertElementInst &IE) {
447447
Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
448448
Value *LHS = SVI.getOperand(0);
449449
Value *RHS = SVI.getOperand(1);
450-
std::vector<int> Mask = getShuffleMask(&SVI);
450+
SmallVector<int, 16> Mask = getShuffleMask(&SVI);
451451

452452
bool MadeChange = false;
453453

@@ -457,9 +457,6 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
457457

458458
unsigned VWidth = cast<VectorType>(SVI.getType())->getNumElements();
459459

460-
if (VWidth != cast<VectorType>(LHS->getType())->getNumElements())
461-
return 0;
462-
463460
APInt UndefElts(VWidth, 0);
464461
APInt AllOnesEltMask(APInt::getAllOnesValue(VWidth));
465462
if (Value *V = SimplifyDemandedVectorElts(&SVI, AllOnesEltMask, UndefElts)) {
@@ -470,17 +467,21 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
470467
MadeChange = true;
471468
}
472469

470+
unsigned LHSWidth = cast<VectorType>(LHS->getType())->getNumElements();
471+
473472
// Canonicalize shuffle(x ,x,mask) -> shuffle(x, undef,mask')
474473
// Canonicalize shuffle(undef,x,mask) -> shuffle(x, undef,mask').
475474
if (LHS == RHS || isa<UndefValue>(LHS)) {
476475
if (isa<UndefValue>(LHS) && LHS == RHS) {
477476
// shuffle(undef,undef,mask) -> undef.
478-
return ReplaceInstUsesWith(SVI, LHS);
477+
Value* result = (VWidth == LHSWidth)
478+
? LHS : UndefValue::get(SVI.getType());
479+
return ReplaceInstUsesWith(SVI, result);
479480
}
480481

481482
// Remap any references to RHS to use LHS.
482483
std::vector<Constant*> Elts;
483-
for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
484+
for (unsigned i = 0, e = LHSWidth; i != VWidth; ++i) {
484485
if (Mask[i] < 0)
485486
Elts.push_back(UndefValue::get(Type::getInt32Ty(SVI.getContext())));
486487
else {
@@ -503,72 +504,205 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
503504
MadeChange = true;
504505
}
505506

506-
// Analyze the shuffle, are the LHS or RHS and identity shuffles?
507-
bool isLHSID = true, isRHSID = true;
507+
if (VWidth == LHSWidth) {
508+
// Analyze the shuffle, are the LHS or RHS and identity shuffles?
509+
bool isLHSID = true, isRHSID = true;
510+
511+
for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
512+
if (Mask[i] < 0) continue; // Ignore undef values.
513+
// Is this an identity shuffle of the LHS value?
514+
isLHSID &= (Mask[i] == (int)i);
508515

509-
for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
510-
if (Mask[i] < 0) continue; // Ignore undef values.
511-
// Is this an identity shuffle of the LHS value?
512-
isLHSID &= (Mask[i] == (int)i);
516+
// Is this an identity shuffle of the RHS value?
517+
isRHSID &= (Mask[i]-e == i);
518+
}
513519

514-
// Is this an identity shuffle of the RHS value?
515-
isRHSID &= (Mask[i]-e == i);
520+
// Eliminate identity shuffles.
521+
if (isLHSID) return ReplaceInstUsesWith(SVI, LHS);
522+
if (isRHSID) return ReplaceInstUsesWith(SVI, RHS);
516523
}
517524

518-
// Eliminate identity shuffles.
519-
if (isLHSID) return ReplaceInstUsesWith(SVI, LHS);
520-
if (isRHSID) return ReplaceInstUsesWith(SVI, RHS);
521-
522525
// If the LHS is a shufflevector itself, see if we can combine it with this
523-
// one without producing an unusual shuffle. Here we are really conservative:
526+
// one without producing an unusual shuffle.
527+
// Cases that might be simplified:
528+
// 1.
529+
// x1=shuffle(v1,v2,mask1)
530+
// x=shuffle(x1,undef,mask)
531+
// ==>
532+
// x=shuffle(v1,undef,newMask)
533+
// newMask[i] = (mask[i] < x1.size()) ? mask1[mask[i]] : -1
534+
// 2.
535+
// x1=shuffle(v1,undef,mask1)
536+
// x=shuffle(x1,x2,mask)
537+
// where v1.size() == mask1.size()
538+
// ==>
539+
// x=shuffle(v1,x2,newMask)
540+
// newMask[i] = (mask[i] < x1.size()) ? mask1[mask[i]] : mask[i]
541+
// 3.
542+
// x2=shuffle(v2,undef,mask2)
543+
// x=shuffle(x1,x2,mask)
544+
// where v2.size() == mask2.size()
545+
// ==>
546+
// x=shuffle(x1,v2,newMask)
547+
// newMask[i] = (mask[i] < x1.size())
548+
// ? mask[i] : mask2[mask[i]-x1.size()]+x1.size()
549+
// 4.
550+
// x1=shuffle(v1,undef,mask1)
551+
// x2=shuffle(v2,undef,mask2)
552+
// x=shuffle(x1,x2,mask)
553+
// where v1.size() == v2.size()
554+
// ==>
555+
// x=shuffle(v1,v2,newMask)
556+
// newMask[i] = (mask[i] < x1.size())
557+
// ? mask1[mask[i]] : mask2[mask[i]-x1.size()]+v1.size()
558+
//
559+
// Here we are really conservative:
524560
// we are absolutely afraid of producing a shuffle mask not in the input
525561
// program, because the code gen may not be smart enough to turn a merged
526562
// shuffle into two specific shuffles: it may produce worse code. As such,
527563
// we only merge two shuffles if the result is either a splat or one of the
528-
// two input shuffle masks. In this case, merging the shuffles just removes
564+
// input shuffle masks. In this case, merging the shuffles just removes
529565
// one instruction, which we know is safe. This is good for things like
530-
// turning: (splat(splat)) -> splat.
531-
if (ShuffleVectorInst *LHSSVI = dyn_cast<ShuffleVectorInst>(LHS)) {
566+
// turning: (splat(splat)) -> splat, or
567+
// merge(V[0..n], V[n+1..2n]) -> V[0..2n]
568+
ShuffleVectorInst* LHSShuffle = dyn_cast<ShuffleVectorInst>(LHS);
569+
ShuffleVectorInst* RHSShuffle = dyn_cast<ShuffleVectorInst>(RHS);
570+
if (LHSShuffle)
571+
if (!isa<UndefValue>(LHSShuffle->getOperand(1)) && !isa<UndefValue>(RHS))
572+
LHSShuffle = NULL;
573+
if (RHSShuffle)
574+
if (!isa<UndefValue>(RHSShuffle->getOperand(1)))
575+
RHSShuffle = NULL;
576+
if (!LHSShuffle && !RHSShuffle)
577+
return MadeChange ? &SVI : 0;
578+
579+
Value* LHSOp0 = NULL;
580+
Value* LHSOp1 = NULL;
581+
Value* RHSOp0 = NULL;
582+
unsigned LHSOp0Width = 0;
583+
unsigned RHSOp0Width = 0;
584+
if (LHSShuffle) {
585+
LHSOp0 = LHSShuffle->getOperand(0);
586+
LHSOp1 = LHSShuffle->getOperand(1);
587+
LHSOp0Width = cast<VectorType>(LHSOp0->getType())->getNumElements();
588+
}
589+
if (RHSShuffle) {
590+
RHSOp0 = RHSShuffle->getOperand(0);
591+
RHSOp0Width = cast<VectorType>(RHSOp0->getType())->getNumElements();
592+
}
593+
Value* newLHS = LHS;
594+
Value* newRHS = RHS;
595+
if (LHSShuffle) {
596+
// case 1
532597
if (isa<UndefValue>(RHS)) {
533-
std::vector<int> LHSMask = getShuffleMask(LHSSVI);
534-
535-
if (LHSMask.size() == Mask.size()) {
536-
std::vector<int> NewMask;
537-
bool isSplat = true;
538-
int SplatElt = -1; // undef
539-
for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
540-
int MaskElt;
541-
if (Mask[i] < 0 || Mask[i] >= (int)e)
542-
MaskElt = -1; // undef
543-
else
544-
MaskElt = LHSMask[Mask[i]];
545-
// Check if this could still be a splat.
546-
if (MaskElt >= 0) {
547-
if (SplatElt >=0 && SplatElt != MaskElt)
548-
isSplat = false;
549-
SplatElt = MaskElt;
550-
}
551-
NewMask.push_back(MaskElt);
552-
}
598+
newLHS = LHSOp0;
599+
newRHS = LHSOp1;
600+
}
601+
// case 2 or 4
602+
else if (LHSOp0Width == LHSWidth) {
603+
newLHS = LHSOp0;
604+
}
605+
}
606+
// case 3 or 4
607+
if (RHSShuffle && RHSOp0Width == LHSWidth) {
608+
newRHS = RHSOp0;
609+
}
610+
// case 4
611+
if (LHSOp0 == RHSOp0) {
612+
newLHS = LHSOp0;
613+
newRHS = NULL;
614+
}
553615

554-
// If the result mask is equal to the src shuffle or this
555-
// shuffle mask, do the replacement.
556-
if (isSplat || NewMask == LHSMask || NewMask == Mask) {
557-
std::vector<Constant*> Elts;
558-
Type *Int32Ty = Type::getInt32Ty(SVI.getContext());
559-
for (unsigned i = 0, e = NewMask.size(); i != e; ++i) {
560-
if (NewMask[i] < 0) {
561-
Elts.push_back(UndefValue::get(Int32Ty));
562-
} else {
563-
Elts.push_back(ConstantInt::get(Int32Ty, NewMask[i]));
564-
}
565-
}
566-
return new ShuffleVectorInst(LHSSVI->getOperand(0),
567-
LHSSVI->getOperand(1),
568-
ConstantVector::get(Elts));
616+
if (newLHS == LHS && newRHS == RHS)
617+
return MadeChange ? &SVI : 0;
618+
619+
SmallVector<int, 16> LHSMask;
620+
SmallVector<int, 16> RHSMask;
621+
if (newLHS != LHS) {
622+
LHSMask = getShuffleMask(LHSShuffle);
623+
}
624+
if (RHSShuffle && newRHS != RHS) {
625+
RHSMask = getShuffleMask(RHSShuffle);
626+
}
627+
unsigned newLHSWidth = (newLHS != LHS) ? LHSOp0Width : LHSWidth;
628+
SmallVector<int, 16> newMask;
629+
bool isSplat = true;
630+
int SplatElt = -1;
631+
// Create a new mask for the new ShuffleVectorInst so that the new
632+
// ShuffleVectorInst is equivalent to the original one.
633+
for (unsigned i = 0; i < VWidth; ++i) {
634+
int eltMask;
635+
if (Mask[i] == -1) {
636+
// This element is an undef value.
637+
eltMask = -1;
638+
} else if (Mask[i] < (int)LHSWidth) {
639+
// This element is from left hand side vector operand.
640+
//
641+
// If LHS is going to be replaced (case 1, 2, or 4), calculate the
642+
// new mask value for the element.
643+
if (newLHS != LHS) {
644+
eltMask = LHSMask[Mask[i]];
645+
// If the value selected is an undef value, explicitly specify it
646+
// with a -1 mask value.
647+
if (eltMask >= (int)LHSOp0Width && isa<UndefValue>(LHSOp1))
648+
eltMask = -1;
649+
}
650+
else
651+
eltMask = Mask[i];
652+
} else {
653+
// This element is from right hand side vector operand
654+
//
655+
// If the value selected is an undef value, explicitly specify it
656+
// with a -1 mask value. (case 1)
657+
if (isa<UndefValue>(RHS))
658+
eltMask = -1;
659+
// If RHS is going to be replaced (case 3 or 4), calculate the
660+
// new mask value for the element.
661+
else if (newRHS != RHS) {
662+
eltMask = RHSMask[Mask[i]-LHSWidth];
663+
// If the value selected is an undef value, explicitly specify it
664+
// with a -1 mask value.
665+
if (eltMask >= (int)RHSOp0Width) {
666+
assert(isa<UndefValue>(RHSShuffle->getOperand(1))
667+
&& "should have been check above");
668+
eltMask = -1;
569669
}
570670
}
671+
else
672+
eltMask = Mask[i]-LHSWidth;
673+
674+
// If LHS's width is changed, shift the mask value accordingly.
675+
// If newRHS == NULL, i.e. LHSOp0 == RHSOp0, we want to remap any
676+
// references to RHSOp0 to LHSOp0, so we don't need to shift the mask.
677+
if (eltMask >= 0 && newRHS != NULL)
678+
eltMask += newLHSWidth;
679+
}
680+
681+
// Check if this could still be a splat.
682+
if (eltMask >= 0) {
683+
if (SplatElt >= 0 && SplatElt != eltMask)
684+
isSplat = false;
685+
SplatElt = eltMask;
686+
}
687+
688+
newMask.push_back(eltMask);
689+
}
690+
691+
// If the result mask is equal to one of the original shuffle masks,
692+
// or is a splat, do the replacement.
693+
if (isSplat || newMask == LHSMask || newMask == RHSMask || newMask == Mask) {
694+
SmallVector<Constant*, 16> Elts;
695+
Type *Int32Ty = Type::getInt32Ty(SVI.getContext());
696+
for (unsigned i = 0, e = newMask.size(); i != e; ++i) {
697+
if (newMask[i] < 0) {
698+
Elts.push_back(UndefValue::get(Int32Ty));
699+
} else {
700+
Elts.push_back(ConstantInt::get(Int32Ty, newMask[i]));
701+
}
571702
}
703+
if (newRHS == NULL)
704+
newRHS = UndefValue::get(newLHS->getType());
705+
return new ShuffleVectorInst(newLHS, newRHS, ConstantVector::get(Elts));
572706
}
573707

574708
return MadeChange ? &SVI : 0;

‎llvm/test/Transforms/InstCombine/vec_shuffle.ll

+46
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,17 @@ define <4 x i8> @test9a(<16 x i8> %tmp6) nounwind {
9898
ret <4 x i8> %tmp9
9999
}
100100

101+
; Test fold of two shuffles where the first shuffle vectors inputs are a
102+
; different length then the second.
103+
define <4 x i8> @test9b(<4 x i8> %tmp6, <4 x i8> %tmp7) nounwind {
104+
; CHECK: @test9
105+
; CHECK-NEXT: shufflevector
106+
; CHECK-NEXT: ret
107+
%tmp1 = shufflevector <4 x i8> %tmp6, <4 x i8> %tmp7, <8 x i32> <i32 0, i32 1, i32 4, i32 5, i32 4, i32 5, i32 2, i32 3> ; <<4 x i8>> [#uses=1]
108+
%tmp9 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <4 x i32> <i32 0, i32 1, i32 4, i32 5> ; <<4 x i8>> [#uses=1]
109+
ret <4 x i8> %tmp9
110+
}
111+
101112
; Redundant vector splats should be removed. Radar 8597790.
102113
define <4 x i32> @test10(<4 x i32> %tmp5) nounwind {
103114
; CHECK: @test10
@@ -107,3 +118,38 @@ define <4 x i32> @test10(<4 x i32> %tmp5) nounwind {
107118
%tmp7 = shufflevector <4 x i32> %tmp6, <4 x i32> undef, <4 x i32> zeroinitializer
108119
ret <4 x i32> %tmp7
109120
}
121+
122+
; Test fold of two shuffles where the two shufflevector inputs's op1 are
123+
; the same
124+
define <8 x i8> @test11(<16 x i8> %tmp6) nounwind {
125+
; CHECK: @test11
126+
; CHECK-NEXT: shufflevector <16 x i8> %tmp6, <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
127+
; CHECK-NEXT: ret
128+
%tmp1 = shufflevector <16 x i8> %tmp6, <16 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> ; <<4 x i8>> [#uses=1]
129+
%tmp2 = shufflevector <16 x i8> %tmp6, <16 x i8> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7> ; <<4 x i8>> [#uses=1]
130+
%tmp3 = shufflevector <4 x i8> %tmp1, <4 x i8> %tmp2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> ; <<8 x i8>> [#uses=1]
131+
ret <8 x i8> %tmp3
132+
}
133+
134+
; Test fold of two shuffles where the first shufflevector's inputs are
135+
; the same as the second
136+
define <8 x i8> @test12(<8 x i8> %tmp6, <8 x i8> %tmp2) nounwind {
137+
; CHECK: @test12
138+
; CHECK-NEXT: shufflevector <8 x i8> %tmp6, <8 x i8> %tmp2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 9, i32 8, i32 11, i32 12>
139+
; CHECK-NEXT: ret
140+
%tmp1 = shufflevector <8 x i8> %tmp6, <8 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 4, i32 undef, i32 7> ; <<8 x i8>> [#uses=1]
141+
%tmp3 = shufflevector <8 x i8> %tmp1, <8 x i8> %tmp2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 9, i32 8, i32 11, i32 12> ; <<8 x i8>> [#uses=1]
142+
ret <8 x i8> %tmp3
143+
}
144+
145+
; Test fold of two shuffles where the first shufflevector's inputs are
146+
; the same as the second
147+
define <8 x i8> @test12a(<8 x i8> %tmp6, <8 x i8> %tmp2) nounwind {
148+
; CHECK: @test12a
149+
; CHECK-NEXT: shufflevector <8 x i8> %tmp2, <8 x i8> %tmp6, <8 x i32> <i32 0, i32 3, i32 1, i32 4, i32 8, i32 9, i32 10, i32 11>
150+
; CHECK-NEXT: ret
151+
%tmp1 = shufflevector <8 x i8> %tmp6, <8 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 4, i32 undef, i32 7> ; <<8 x i8>> [#uses=1]
152+
%tmp3 = shufflevector <8 x i8> %tmp2, <8 x i8> %tmp1, <8 x i32> <i32 0, i32 3, i32 1, i32 4, i32 8, i32 9, i32 10, i32 11> ; <<8 x i8>> [#uses=1]
153+
ret <8 x i8> %tmp3
154+
}
155+

0 commit comments

Comments
 (0)
Please sign in to comment.