aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-05-26 00:29:06 +0000
committerChris Lattner <sabre@nondot.org>2006-05-26 00:29:06 +0000
commit7b2e2792d6877015472100f7f4e98dbdebc1ba84 (patch)
tree9b13f8deca7225f208c108b36ef16141d49a8fdb
parent863bcff18370ad9287ec296c5451ccd0c3816b74 (diff)
Transform things like (splat(splat)) -> splat
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28490 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp54
1 files changed, 50 insertions, 4 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 6196ccf17e..1264e55497 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -7398,18 +7398,26 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
// Remap any references to RHS to use LHS.
std::vector<Constant*> Elts;
for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
- if (Mask[i] > 2*e)
+ if (Mask[i] >= 2*e)
Elts.push_back(UndefValue::get(Type::UIntTy));
- else
- Elts.push_back(ConstantUInt::get(Type::UIntTy, Mask[i] & (e-1)));
+ else {
+ if ((Mask[i] >= e && isa<UndefValue>(RHS)) ||
+ (Mask[i] < e && isa<UndefValue>(LHS)))
+ Mask[i] = 2*e; // Turn into undef.
+ else
+ Mask[i] &= (e-1); // Force to LHS.
+ Elts.push_back(ConstantUInt::get(Type::UIntTy, Mask[i]));
+ }
}
SVI.setOperand(0, SVI.getOperand(1));
SVI.setOperand(1, UndefValue::get(RHS->getType()));
SVI.setOperand(2, ConstantPacked::get(Elts));
+ LHS = SVI.getOperand(0);
+ RHS = SVI.getOperand(1);
MadeChange = true;
}
- // Analyze the shuffle, are the LHS or RHS and identity shuffle?
+ // Analyze the shuffle, are the LHS or RHS and identity shuffles?
bool isLHSID = true, isRHSID = true;
for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
@@ -7425,6 +7433,44 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
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<ShuffleVectorInst>(LHS)) {
+ if (isa<UndefValue>(RHS)) {
+ std::vector<unsigned> LHSMask = getShuffleMask(LHSSVI);
+
+ std::vector<unsigned> NewMask;
+ for (unsigned i = 0, e = Mask.size(); i != e; ++i)
+ if (Mask[i] >= 2*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<Constant*> Elts;
+ for (unsigned i = 0, e = NewMask.size(); i != e; ++i) {
+ if (NewMask[i] >= e*2) {
+ Elts.push_back(UndefValue::get(Type::UIntTy));
+ } else {
+ Elts.push_back(ConstantUInt::get(Type::UIntTy, NewMask[i]));
+ }
+ }
+ return new ShuffleVectorInst(LHSSVI->getOperand(0),
+ LHSSVI->getOperand(1),
+ ConstantPacked::get(Elts));
+ }
+ }
+ }
+
return MadeChange ? &SVI : 0;
}