From a844fc4cb026cbc5e29f5cd0d97c110147de3828 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 10 Apr 2006 22:45:52 +0000 Subject: [PATCH] Implement InstCombine/vec_shuffle.ll:test[12] git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27571 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index bfa4964636a..7674bd2389e 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -138,6 +138,7 @@ namespace { Instruction *visitBranchInst(BranchInst &BI); Instruction *visitSwitchInst(SwitchInst &SI); Instruction *visitExtractElementInst(ExtractElementInst &EI); + Instruction *visitShuffleVectorInst(ShuffleVectorInst &SVI); // visitInstruction - Specify what to return for unhandled instructions... Instruction *visitInstruction(Instruction &I) { return 0; } @@ -6876,6 +6877,67 @@ Instruction *InstCombiner::visitExtractElementInst(ExtractElementInst &EI) { return 0; } +Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) { + Value *LHS = SVI.getOperand(0); + Value *RHS = SVI.getOperand(1); + Constant *Mask = cast(SVI.getOperand(2)); + + bool MadeChange = false; + + if (isa(Mask)) + return ReplaceInstUsesWith(SVI, UndefValue::get(SVI.getType())); + + // Canonicalize shuffle(x,x) -> shuffle(x,undef) + if (LHS == RHS) { + if (isa(LHS)) { + // shuffle(undef,undef,mask) -> undef. + return ReplaceInstUsesWith(SVI, LHS); + } + + if (!isa(Mask)) { + // Remap any references to RHS to use LHS. + ConstantPacked *CP = cast(Mask); + std::vector Elts; + for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) { + Elts.push_back(CP->getOperand(i)); + if (isa(CP->getOperand(i))) + continue; + unsigned MV = cast(CP->getOperand(i))->getRawValue(); + if (MV >= e) + Elts.back() = ConstantUInt::get(Type::UIntTy, MV & (e-1)); + } + Mask = ConstantPacked::get(Elts); + } + SVI.setOperand(1, UndefValue::get(RHS->getType())); + SVI.setOperand(2, Mask); + MadeChange = true; + } + + if (ConstantPacked *CP = dyn_cast(Mask)) { + bool isLHSID = true, isRHSID = true; + + // Analyze the shuffle. + for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) { + if (isa(CP->getOperand(i))) + continue; + unsigned MV = cast(CP->getOperand(i))->getRawValue(); + + // Is this an identity shuffle of the LHS value? + isLHSID &= (MV == i); + + // Is this an identity shuffle of the RHS value? + isRHSID &= (MV-e == i); + } + + // Eliminate identity shuffles. + if (isLHSID) return ReplaceInstUsesWith(SVI, LHS); + if (isRHSID) return ReplaceInstUsesWith(SVI, RHS); + } + + return MadeChange ? &SVI : 0; +} + + void InstCombiner::removeFromWorkList(Instruction *I) { WorkList.erase(std::remove(WorkList.begin(), WorkList.end(), I),