From 74862789001b62350fa1a316150fdab04689a0bc Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Thu, 12 Aug 2010 07:01:22 +0000 Subject: [PATCH] Temporarily revert 110737 and 110734, they were causing failures in an external testsuite. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@110905 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineVectorOps.cpp | 207 ++++++------------ test/Transforms/InstCombine/vec_shuffle.ll | 29 --- 2 files changed, 65 insertions(+), 171 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index 8c987b67b7f..a58124d7032 100644 --- a/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -448,8 +448,10 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) { if (isa(SVI.getOperand(2))) return ReplaceInstUsesWith(SVI, UndefValue::get(SVI.getType())); - unsigned VWidth = Mask.size(); - unsigned LHSWidth = cast(LHS->getType())->getNumElements(); + unsigned VWidth = cast(SVI.getType())->getNumElements(); + + if (VWidth != cast(LHS->getType())->getNumElements()) + return 0; APInt UndefElts(VWidth, 0); APInt AllOnesEltMask(APInt::getAllOnesValue(VWidth)); @@ -462,12 +464,14 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) { // Canonicalize shuffle(x ,x,mask) -> shuffle(x, undef,mask') // Canonicalize shuffle(undef,x,mask) -> shuffle(x, undef,mask'). if (LHS == RHS || isa(LHS)) { - if (isa(LHS) && LHS == RHS) - return ReplaceInstUsesWith(SVI, UndefValue::get(SVI.getType())); + if (isa(LHS) && LHS == RHS) { + // shuffle(undef,undef,mask) -> undef. + return ReplaceInstUsesWith(SVI, LHS); + } // Remap any references to RHS to use LHS. std::vector Elts; - for (unsigned i = 0, e = LHSWidth; i != VWidth; ++i) { + for (unsigned i = 0, e = Mask.size(); i != e; ++i) { if (Mask[i] >= 2*e) Elts.push_back(UndefValue::get(Type::getInt32Ty(SVI.getContext()))); else { @@ -491,148 +495,67 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) { } // Analyze the shuffle, are the LHS or RHS and identity shuffles? - if (VWidth == LHSWidth) { - bool isLHSID = true, isRHSID = true; + bool isLHSID = true, isRHSID = true; + + for (unsigned i = 0, e = Mask.size(); i != e; ++i) { + if (Mask[i] >= e*2) continue; // Ignore undef values. + // Is this an identity shuffle of the LHS value? + isLHSID &= (Mask[i] == i); - for (unsigned i = 0, e = Mask.size(); i != e; ++i) { - if (Mask[i] >= e*2) continue; // Ignore undef values. - // Is this an identity shuffle of the LHS value? - isLHSID &= (Mask[i] == i); + // Is this an identity shuffle of the RHS value? + isRHSID &= (Mask[i]-e == i); + } + + // Eliminate identity shuffles. + if (isLHSID) return ReplaceInstUsesWith(SVI, LHS); + if (isRHSID) return ReplaceInstUsesWith(SVI, RHS); + + // If the LHS is a shufflevector itself, see if we can combine it with this + // one without producing an unusual shuffle. Here we are really conservative: + // we are absolutely afraid of producing a shuffle mask not in the input + // program, because the code gen may not be smart enough to turn a merged + // shuffle into two specific shuffles: it may produce worse code. As such, + // we only merge two shuffles if the result is one of the two input shuffle + // masks. In this case, merging the shuffles just removes one instruction, + // which we know is safe. This is good for things like turning: + // (splat(splat)) -> splat. + if (ShuffleVectorInst *LHSSVI = dyn_cast(LHS)) { + if (isa(RHS)) { + std::vector LHSMask = getShuffleMask(LHSSVI); - // Is this an identity shuffle of the RHS value? - isRHSID &= (Mask[i]-e == i); - } - - // Eliminate identity shuffles. - if (isLHSID) return ReplaceInstUsesWith(SVI, LHS); - if (isRHSID) return ReplaceInstUsesWith(SVI, RHS); - } - - // Check for a handful of important shuffle(shuffle()) combinations. - ShuffleVectorInst *LSVI = dyn_cast(LHS); - if (!LSVI) - return MadeChange ? &SVI : 0; - - LHS = LSVI->getOperand(0); - std::vector LHSMask = getShuffleMask(LSVI); - unsigned LHSInNElts = cast(LHS->getType())->getNumElements(); - - // If lhs is identity, propagate - bool isLHSLoExtract = true, isLHSHiExtract = true; - for (unsigned i = 0, e = LHSMask.size(); i != e; ++i) { - if (LHSMask[i] >= LHSInNElts*2) continue; // Ignore undef values; - isLHSLoExtract &= (LHSMask[i] == i); - isLHSHiExtract &= (LHSMask[i] == i+(LHSInNElts/2)); - } - if ((isLHSLoExtract || isLHSHiExtract) && - (isa(RHS) || (LHSWidth == LHSInNElts))) { - std::vector Elts; - for (unsigned i = 0, e = VWidth; i != e; ++i) { - if (Mask[i] >= 2*LHSWidth) - Elts.push_back(UndefValue::get(Type::getInt32Ty(SVI.getContext()))); - else - Elts.push_back(ConstantInt::get(Type::getInt32Ty(SVI.getContext()), - LHSMask[Mask[i]])); - } - if (isa(RHS)) - RHS = UndefValue::get(LHS->getType()); - return new ShuffleVectorInst(LHS, RHS, ConstantVector::get(Elts)); - } - - // If svi + lhs forms a full unpack, merge it. This allows llvm to emit - // efficient code for matrix transposes written with generic vector ops. - if ((LHSMask.size() == Mask.size()) && isPowerOf2_32(Mask.size()) && - (Mask.size() > 1)) { - bool isUnpackLo = true, isUnpackHi = true; - // check lhs mask for <0, u, 1, u .. >; - for (unsigned i = 0, e = LHSMask.size(); i != e; ++i) { - if (LHSMask[i] >= 2*e) continue; - isUnpackLo &= (LHSMask[i] == (i/2)); - isUnpackHi &= (LHSMask[i] == (i/2) + (e/2)); - } - for (unsigned i = 0, e = Mask.size(); i != e && (isUnpackLo || isUnpackHi); - i += 2) { - isUnpackLo &= (Mask[i] == i) && (Mask[i+1] == (i/2)+e); - isUnpackHi &= (Mask[i] == i) && (Mask[i+1] == (i/2)+e+(e/2)); - } - if (isUnpackLo || isUnpackHi) { - std::vector Elts; - for (unsigned i = 0, e = Mask.size(); i != e; ++i) { - if (Mask[i] >= 2*e) - Elts.push_back(UndefValue::get(Type::getInt32Ty(SVI.getContext()))); - else if (Mask[i] >= e) - Elts.push_back(ConstantInt::get(Type::getInt32Ty(SVI.getContext()), - Mask[i])); - else - Elts.push_back(ConstantInt::get(Type::getInt32Ty(SVI.getContext()), - LHSMask[Mask[i]])); - } - return new ShuffleVectorInst(LHS, RHS, ConstantVector::get(Elts)); - } - } - - // If rhs is shuffle + identity, propagate. - if (ShuffleVectorInst *RSVI = dyn_cast(RHS)) { - std::vector RHSMask = getShuffleMask(RSVI); - unsigned RHSInNElts = - cast(RSVI->getOperand(0)->getType())->getNumElements(); - - // If rhs is identity, propagate - bool isRHSLoExtract = true, isRHSHiExtract = true; - for (unsigned i = 0, e = RHSMask.size(); i != e; ++i) { - if (RHSMask[i] >= RHSInNElts*2) continue; // Ignore undef values; - isRHSLoExtract &= (RHSMask[i] == i); - isRHSHiExtract &= (RHSMask[i] == i+(RHSInNElts/2)); - } - if ((isRHSLoExtract || isRHSHiExtract) && (LHSWidth == RHSInNElts)) { - std::vector Elts; - for (unsigned i = 0, e = VWidth; i != e; ++i) { - if (Mask[i] >= 2*LHSWidth) - Elts.push_back(UndefValue::get(Type::getInt32Ty(SVI.getContext()))); - else if (Mask[i] < LHSWidth) - Elts.push_back(ConstantInt::get(Type::getInt32Ty(SVI.getContext()), - Mask[i])); - else - Elts.push_back(ConstantInt::get(Type::getInt32Ty(SVI.getContext()), - RHSMask[Mask[i]-LHSWidth]+LHSWidth)); - } - SVI.setOperand(1, RSVI->getOperand(0)); - SVI.setOperand(2, ConstantVector::get(Elts)); - return &SVI; - } - } - - // Be extremely conservative when merging shufflevector instructions. It is - // difficult for the code generator to recognize a merged shuffle, which - // usually leads to worse code from merging a shuffle. - if (!isa(RHS)) - return MadeChange ? &SVI : 0; - - // If the merged shuffle mask is one of the two input shuffle masks, which - // just removes one instruction. This should handle splat(splat) -> splat. - if (LHSMask.size() == Mask.size()) { - std::vector NewMask; - for (unsigned i = 0, e = Mask.size(); i != e; ++i) - if (Mask[i] >= e) - NewMask.push_back(2*e); - else - NewMask.push_back(LHSMask[Mask[i]]); - - // If the result mask is equal to the src shuffle or this shuffle mask, - // do the replacement. - if (NewMask == LHSMask || NewMask == Mask) { - std::vector Elts; - for (unsigned i = 0, e = NewMask.size(); i != e; ++i) { - if (NewMask[i] >= LHSInNElts*2) { - Elts.push_back(UndefValue::get(Type::getInt32Ty(SVI.getContext()))); - } else { - Elts.push_back(ConstantInt::get(Type::getInt32Ty(SVI.getContext()), - NewMask[i])); + if (LHSMask.size() == Mask.size()) { + std::vector NewMask; + for (unsigned i = 0, e = Mask.size(); i != e; ++i) + if (Mask[i] >= e) + NewMask.push_back(2*e); + else + NewMask.push_back(LHSMask[Mask[i]]); + + // If the result mask is equal to the src shuffle or this + // shuffle mask, do the replacement. + if (NewMask == LHSMask || NewMask == Mask) { + unsigned LHSInNElts = + cast(LHSSVI->getOperand(0)->getType())-> + getNumElements(); + std::vector Elts; + for (unsigned i = 0, e = NewMask.size(); i != e; ++i) { + if (NewMask[i] >= LHSInNElts*2) { + Elts.push_back(UndefValue::get( + Type::getInt32Ty(SVI.getContext()))); + } else { + Elts.push_back(ConstantInt::get( + Type::getInt32Ty(SVI.getContext()), + NewMask[i])); + } + } + return new ShuffleVectorInst(LHSSVI->getOperand(0), + LHSSVI->getOperand(1), + ConstantVector::get(Elts)); } } - return new ShuffleVectorInst(LHS, LSVI->getOperand(1), - ConstantVector::get(Elts)); } } + return MadeChange ? &SVI : 0; } + diff --git a/test/Transforms/InstCombine/vec_shuffle.ll b/test/Transforms/InstCombine/vec_shuffle.ll index 21fe08a8f02..5132a8ff9bd 100644 --- a/test/Transforms/InstCombine/vec_shuffle.ll +++ b/test/Transforms/InstCombine/vec_shuffle.ll @@ -87,32 +87,3 @@ define <4 x i8> @test9(<16 x i8> %tmp6) nounwind { %tmp9 = shufflevector <4 x i8> %tmp7, <4 x i8> undef, <4 x i32> < i32 3, i32 1, i32 2, i32 0 > ; <<4 x i8>> [#uses=1] ret <4 x i8> %tmp9 } - -; Test fold of hi/lo vector halves -; Test fold of unpack operation -define void @test10(<16 x i8>* %out, <16 x i8> %r, <16 x i8> %g, <16 x i8> %b, <16 x i8> %a) nounwind ssp { -; CHECK: @test10 -; CHECK-NEXT: shufflevector -; CHECK-NEXT: shufflevector -; CHECK-NEXT: store -; CHECK-NEXT: getelementptr -; CHECK-NEXT: store -; CHECK-NEXT: ret - %tmp1 = shufflevector <16 x i8> %r, <16 x i8> undef, <8 x i32> ; <<8 x i8>> [#uses=1] - %tmp3 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <16 x i32> ; <<16 x i8>> [#uses=1] - %tmp4 = shufflevector <16 x i8> undef, <16 x i8> %tmp3, <16 x i32> ; <<16 x i8>> [#uses=1] - %tmp6 = shufflevector <16 x i8> %b, <16 x i8> undef, <8 x i32> ; <<8 x i8>> [#uses=1] - %tmp8 = shufflevector <8 x i8> %tmp6, <8 x i8> undef, <16 x i32> ; <<16 x i8>> [#uses=1] - %tmp9 = shufflevector <16 x i8> %tmp4, <16 x i8> %tmp8, <16 x i32> ; <<16 x i8>> [#uses=1] - %tmp11 = shufflevector <16 x i8> %r, <16 x i8> undef, <8 x i32> ; <<8 x i8>> [#uses=1] - %tmp13 = shufflevector <8 x i8> %tmp11, <8 x i8> undef, <16 x i32> ; <<16 x i8>> [#uses=1] - %tmp14 = shufflevector <16 x i8> undef, <16 x i8> %tmp13, <16 x i32> ; <<16 x i8>> [#uses=1] - %tmp16 = shufflevector <16 x i8> %b, <16 x i8> undef, <8 x i32> ; <<8 x i8>> [#uses=1] - %tmp18 = shufflevector <8 x i8> %tmp16, <8 x i8> undef, <16 x i32> ; <<16 x i8>> [#uses=1] - %tmp19 = shufflevector <16 x i8> %tmp14, <16 x i8> %tmp18, <16 x i32> ; <<16 x i8>> [#uses=1] - %arrayidx = getelementptr inbounds <16 x i8>* %out, i64 0 ; <<16 x i8>*> [#uses=1] - store <16 x i8> %tmp9, <16 x i8>* %arrayidx - %arrayidx24 = getelementptr inbounds <16 x i8>* %out, i64 1 ; <<16 x i8>*> [#uses=1] - store <16 x i8> %tmp19, <16 x i8>* %arrayidx24 - ret void -}