diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h index b3084ccd2c5..b1eefd214d5 100644 --- a/lib/Transforms/InstCombine/InstCombine.h +++ b/lib/Transforms/InstCombine/InstCombine.h @@ -234,7 +234,6 @@ private: bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS); Value *EmitGEPOffset(User *GEP); Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN); - Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef Mask); public: // InsertNewInstBefore - insert an instruction New before instruction Old diff --git a/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index ffab87faf68..d4344c3c4d6 100644 --- a/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -494,241 +494,6 @@ Instruction *InstCombiner::visitInsertElementInst(InsertElementInst &IE) { return 0; } -/// Return true if we can evaluate the specified expression tree if the vector -/// elements were shuffled in a different order. -static bool CanEvaluateShuffled(Value *V, ArrayRef Mask, - unsigned Depth = 100) { - // We can always reorder the elements of a constant. - if (isa(V)) - return true; - - // We won't reorder vector arguments. No IPO here. - Instruction *I = dyn_cast(V); - if (!I) return false; - - // Two users may expect different orders of the elements. Don't try it. - if (!I->hasOneUse()) - return false; - - if (Depth == 0) return false; - - switch (I->getOpcode()) { - case Instruction::Add: - case Instruction::FAdd: - case Instruction::Sub: - case Instruction::FSub: - case Instruction::Mul: - case Instruction::FMul: - case Instruction::UDiv: - case Instruction::SDiv: - case Instruction::FDiv: - case Instruction::URem: - case Instruction::SRem: - case Instruction::FRem: - case Instruction::Shl: - case Instruction::LShr: - case Instruction::AShr: - case Instruction::And: - case Instruction::Or: - case Instruction::Xor: - case Instruction::ICmp: - case Instruction::FCmp: - case Instruction::Trunc: - case Instruction::ZExt: - case Instruction::SExt: - case Instruction::FPToUI: - case Instruction::FPToSI: - case Instruction::UIToFP: - case Instruction::SIToFP: - case Instruction::FPTrunc: - case Instruction::FPExt: - case Instruction::GetElementPtr: { - for (int i = 0, e = I->getNumOperands(); i != e; ++i) { - if (!CanEvaluateShuffled(I->getOperand(i), Mask, Depth-1)) - return false; - } - return true; - } - case Instruction::InsertElement: { - ConstantInt *CI = dyn_cast(I->getOperand(2)); - if (!CI) return false; - int ElementNumber = CI->getLimitedValue(); - - // Verify that 'CI' does not occur twice in Mask. A single 'insertelement' - // can't put an element into multiple indices. - bool SeenOnce = false; - for (int i = 0, e = Mask.size(); i != e; ++i) { - if (Mask[i] == ElementNumber) { - if (SeenOnce) - return false; - SeenOnce = true; - } - } - return CanEvaluateShuffled(I->getOperand(0), Mask, Depth-1); - } - } - return false; -} - -/// Rebuild a new instruction just like 'I' but with the new operands given. -/// In the event of type mismatch, the type of the operands is correct. -static Value *BuildNew(Instruction *I, ArrayRef NewOps) { - // We don't want to use the IRBuilder here because we want the replacement - // instructions to appear next to 'I', not the builder's insertion point. - switch (I->getOpcode()) { - case Instruction::Add: - case Instruction::FAdd: - case Instruction::Sub: - case Instruction::FSub: - case Instruction::Mul: - case Instruction::FMul: - case Instruction::UDiv: - case Instruction::SDiv: - case Instruction::FDiv: - case Instruction::URem: - case Instruction::SRem: - case Instruction::FRem: - case Instruction::Shl: - case Instruction::LShr: - case Instruction::AShr: - case Instruction::And: - case Instruction::Or: - case Instruction::Xor: { - BinaryOperator *BO = cast(I); - assert(NewOps.size() == 2 && "binary operator with #ops != 2"); - BinaryOperator *New = - BinaryOperator::Create(cast(I)->getOpcode(), - NewOps[0], NewOps[1], "", BO); - if (isa(BO)) { - New->setHasNoUnsignedWrap(BO->hasNoUnsignedWrap()); - New->setHasNoSignedWrap(BO->hasNoSignedWrap()); - } - if (isa(BO)) { - New->setIsExact(BO->isExact()); - } - return New; - } - case Instruction::ICmp: - assert(NewOps.size() == 2 && "icmp with #ops != 2"); - return new ICmpInst(I, cast(I)->getPredicate(), - NewOps[0], NewOps[1]); - case Instruction::FCmp: - assert(NewOps.size() == 2 && "fcmp with #ops != 2"); - return new FCmpInst(I, cast(I)->getPredicate(), - NewOps[0], NewOps[1]); - case Instruction::Trunc: - case Instruction::ZExt: - case Instruction::SExt: - case Instruction::FPToUI: - case Instruction::FPToSI: - case Instruction::UIToFP: - case Instruction::SIToFP: - case Instruction::FPTrunc: - case Instruction::FPExt: { - // It's possible that the mask has a different number of elements from - // the original cast. We recompute the destination type to match the mask. - Type *DestTy = - VectorType::get(I->getType()->getScalarType(), - NewOps[0]->getType()->getVectorNumElements()); - assert(NewOps.size() == 1 && "cast with #ops != 1"); - return CastInst::Create(cast(I)->getOpcode(), NewOps[0], DestTy, - "", I); - } - case Instruction::GetElementPtr: { - Value *Ptr = NewOps[0]; - ArrayRef Idx = NewOps.slice(1); - GetElementPtrInst *GEP = GetElementPtrInst::Create(Ptr, Idx, "", I); - GEP->setIsInBounds(cast(I)->isInBounds()); - return GEP; - } - } - llvm_unreachable("failed to rebuild vector instructions"); -} - -Value * -InstCombiner::EvaluateInDifferentElementOrder(Value *V, ArrayRef Mask) { - // Mask.size() does not need to be equal to the number of vector elements. - - assert(V->getType()->isVectorTy() && "can't reorder non-vector elements"); - if (isa(V)) { - return UndefValue::get(VectorType::get(V->getType()->getScalarType(), - Mask.size())); - } - if (isa(V)) { - return ConstantAggregateZero::get( - VectorType::get(V->getType()->getScalarType(), - Mask.size())); - } - if (Constant *C = dyn_cast(V)) { - SmallVector MaskValues; - for (int i = 0, e = Mask.size(); i != e; ++i) { - if (Mask[i] == -1) - MaskValues.push_back(UndefValue::get(Builder->getInt32Ty())); - else - MaskValues.push_back(Builder->getInt32(Mask[i])); - } - return ConstantExpr::getShuffleVector(C, UndefValue::get(C->getType()), - ConstantVector::get(MaskValues)); - } - - Instruction *I = cast(V); - switch (I->getOpcode()) { - case Instruction::Add: - case Instruction::FAdd: - case Instruction::Sub: - case Instruction::FSub: - case Instruction::Mul: - case Instruction::FMul: - case Instruction::UDiv: - case Instruction::SDiv: - case Instruction::FDiv: - case Instruction::URem: - case Instruction::SRem: - case Instruction::FRem: - case Instruction::Shl: - case Instruction::LShr: - case Instruction::AShr: - case Instruction::And: - case Instruction::Or: - case Instruction::Xor: - case Instruction::ICmp: - case Instruction::FCmp: - case Instruction::Trunc: - case Instruction::ZExt: - case Instruction::SExt: - case Instruction::FPToUI: - case Instruction::FPToSI: - case Instruction::UIToFP: - case Instruction::SIToFP: - case Instruction::FPTrunc: - case Instruction::FPExt: - case Instruction::Select: - case Instruction::GetElementPtr: { - SmallVector NewOps; - bool NeedsRebuild = (Mask.size() != I->getType()->getVectorNumElements()); - for (int i = 0, e = I->getNumOperands(); i != e; ++i) { - Value *V = EvaluateInDifferentElementOrder(I->getOperand(i), Mask); - NewOps.push_back(V); - NeedsRebuild |= (V != I->getOperand(i)); - } - if (NeedsRebuild) { - return BuildNew(I, NewOps); - } - return I; - } - case Instruction::InsertElement: { - uint32_t Element = cast(I->getOperand(2))->getLimitedValue(); - if (Element >= Mask.size()) { - // Such instructions are valid and exhibit undefined behaviour. - return UndefValue::get(I->getType()); - } - Value *V = EvaluateInDifferentElementOrder(I->getOperand(0), Mask); - return InsertElementInst::Create(V, I->getOperand(1), - Builder->getInt32(Mask[Element]), "", I); - } - } - llvm_unreachable("failed to reorder elements of vector instruction!"); -} Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) { Value *LHS = SVI.getOperand(0); @@ -809,16 +574,6 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) { if (isRHSID) return ReplaceInstUsesWith(SVI, RHS); } - if (isa(RHS) && - // This isn't necessary for correctness, but the comment block below - // claims that there are cases where folding two shuffles into one would - // cause worse codegen on some targets. - !isa(LHS) && - CanEvaluateShuffled(LHS, Mask)) { - Value *V = EvaluateInDifferentElementOrder(LHS, Mask); - return ReplaceInstUsesWith(SVI, V); - } - // If the LHS is a shufflevector itself, see if we can combine it with this // one without producing an unusual shuffle. // Cases that might be simplified: diff --git a/test/Transforms/InstCombine/vec_shuffle.ll b/test/Transforms/InstCombine/vec_shuffle.ll index 9dc29e4c6cd..8f78c2e6bd5 100644 --- a/test/Transforms/InstCombine/vec_shuffle.ll +++ b/test/Transforms/InstCombine/vec_shuffle.ll @@ -153,15 +153,3 @@ define <8 x i8> @test12a(<8 x i8> %tmp6, <8 x i8> %tmp2) nounwind { ret <8 x i8> %tmp3 } -define <2 x i8> @test13(i8 %x1, i8 %x2) { -; CHECK: @test13 -; CHECK-NEXT: insertelement {{.*}} undef, i8 %x1, i32 1 -; CHECK-NEXT: insertelement {{.*}} i8 %x2, i32 0 -; CHECK-NEXT: add {{.*}} -; CHECK-NEXT: ret - %A = insertelement <2 x i8> undef, i8 %x1, i32 0 - %B = insertelement <2 x i8> %A, i8 %x2, i32 1 - %C = add <2 x i8> %B, - %D = shufflevector <2 x i8> %C, <2 x i8> undef, <2 x i32> - ret <2 x i8> %D -}