Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -4137,22 +4137,12 @@ static Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask, Type *RetTy, const Query &Q, unsigned MaxRecurse) { - if (isa(Mask)) - return UndefValue::get(RetTy); - Type *InVecTy = Op0->getType(); unsigned MaskNumElts = Mask->getType()->getVectorNumElements(); unsigned InVecNumElts = InVecTy->getVectorNumElements(); - auto *Op0Const = dyn_cast(Op0); - auto *Op1Const = dyn_cast(Op1); - - // If all operands are constant, constant fold the shuffle. - if (Op0Const && Op1Const) - return ConstantFoldShuffleVectorInstruction(Op0Const, Op1Const, Mask); - - // If only one of the operands is constant, constant fold the shuffle if the - // mask does not select elements from the variable operand. + // Canonicalization: If mask does not select elements from an input vector, + // replace that input vector with undef. bool MaskSelects0 = false, MaskSelects1 = false; for (unsigned i = 0; i != MaskNumElts; ++i) { int Idx = ShuffleVectorInst::getMaskValue(Mask, i); @@ -4163,30 +4153,47 @@ else MaskSelects1 = true; } - if (!MaskSelects0 && Op1Const) - return ConstantFoldShuffleVectorInstruction(UndefValue::get(InVecTy), - Op1Const, Mask); - if (!MaskSelects1 && Op0Const) - return ConstantFoldShuffleVectorInstruction(Op0Const, - UndefValue::get(InVecTy), Mask); + if (!MaskSelects0) + Op0 = UndefValue::get(InVecTy); + if (!MaskSelects1) + Op1 = UndefValue::get(InVecTy); + + auto *Op0Const = dyn_cast(Op0); + auto *Op1Const = dyn_cast(Op1); + + // If all operands are constant, constant fold the shuffle. + if (Op0Const && Op1Const) + return ConstantFoldShuffleVectorInstruction(Op0Const, Op1Const, Mask); + + bool MaskHasAnyUndefs = false; + // Canonicalization: if only one input vector is contant, it shall be the + // second one. + if (Op0Const && !Op1Const) { + std::swap(Op0, Op1); + SmallVector NewIndices; + for (unsigned i = 0; i != MaskNumElts; ++i) { + int Idx = ShuffleVectorInst::getMaskValue(Mask, i); + if (Idx != -1) + NewIndices.push_back(Idx < (int)MaskNumElts ? Idx + MaskNumElts + : Idx - MaskNumElts); + else + MaskHasAnyUndefs = true; + } + Mask = ConstantDataVector::get(Mask->getContext(), NewIndices); + } // A shuffle of a splat is always the splat itself. Legal if the shuffle's // value type is same as the input vectors' type. if (auto *OpShuf = dyn_cast(Op0)) - if (!MaskSelects1 && RetTy == InVecTy && + if (isa(Op1) && RetTy == InVecTy && OpShuf->getMask()->getSplatValue()) return Op0; - if (auto *OpShuf = dyn_cast(Op1)) - if (!MaskSelects0 && RetTy == InVecTy && - OpShuf->getMask()->getSplatValue()) - return Op1; // Don't fold a shuffle with undef mask elements. This may get folded in a // better way using demanded bits or other analysis. // TODO: Should we allow this? - for (unsigned i = 0; i != MaskNumElts; ++i) - if (ShuffleVectorInst::getMaskValue(Mask, i) == -1) - return nullptr; + if (MaskHasAnyUndefs) + return nullptr; // Check if every element of this shuffle can be mapped back to the // corresponding element of a single root vector. If so, we don't need this