}
/// Checks if the given value is actually an undefined constant vector.
-static bool isUndefVector(const Value *V) {
+/// Also, if the\p ShuffleMask is not empty, tries to check if the non-masked
+/// elements actually mask the insertelement buildvector, if any.
+static bool isUndefVector(const Value *V, ArrayRef<int> ShuffleMask = None) {
if (isa<UndefValue>(V))
return true;
- auto *C = dyn_cast<Constant>(V);
- if (!C)
- return false;
- if (!C->containsUndefOrPoisonElement())
- return false;
- auto *VecTy = dyn_cast<FixedVectorType>(C->getType());
+ auto *VecTy = dyn_cast<FixedVectorType>(V->getType());
if (!VecTy)
return false;
+ auto *C = dyn_cast<Constant>(V);
+ if (!C) {
+ if (!ShuffleMask.empty()) {
+ const Value *Base = V;
+ while (auto *II = dyn_cast<InsertElementInst>(Base)) {
+ Base = II->getOperand(0);
+ Optional<unsigned> Idx = getInsertIndex(II);
+ if (!Idx)
+ continue;
+ if (*Idx < ShuffleMask.size() && ShuffleMask[*Idx] == UndefMaskElem)
+ return false;
+ }
+ return V != Base && isUndefVector(Base);
+ }
+ return false;
+ }
for (unsigned I = 0, E = VecTy->getNumElements(); I != E; ++I) {
if (Constant *Elem = C->getAggregateElement(I))
- if (!isa<UndefValue>(Elem))
+ if (!isa<UndefValue>(Elem) &&
+ (ShuffleMask.empty() ||
+ (I < ShuffleMask.size() && ShuffleMask[I] == UndefMaskElem)))
return false;
}
return true;
// initial vector or inserting a subvector.
// TODO: Implement the analysis of the FirstInsert->getOperand(0)
// subvector of ActualVecTy.
- if (!isUndefVector(FirstInsert->getOperand(0)) && NumScalars != NumElts &&
- !IsWholeSubvector) {
+ SmallVector<int> InsertMask(NumElts, UndefMaskElem);
+ copy(Mask, std::next(InsertMask.begin(), OffsetBeg));
+ if (!isUndefVector(FirstInsert->getOperand(0), InsertMask) &&
+ NumScalars != NumElts && !IsWholeSubvector) {
if (InsertVecSz != VecSz) {
auto *ActualVecTy =
FixedVectorType::get(SrcVecTy->getElementType(), VecSz);
SmallVector<int> Mask(ShuffleMask.begin()->second);
auto VMIt = std::next(ShuffleMask.begin());
T *Prev = nullptr;
- bool IsBaseNotUndef = !isUndefVector(Base);
+ bool IsBaseNotUndef = !isUndefVector(Base, Mask);
if (IsBaseNotUndef) {
// Base is not undef, need to combine it with the next subvectors.
std::pair<T *, bool> Res =
}
}
- if ((!IsIdentity || Offset != 0 ||
- !isUndefVector(FirstInsert->getOperand(0))) &&
- NumElts != NumScalars) {
- SmallVector<int> InsertMask(NumElts);
- std::iota(InsertMask.begin(), InsertMask.end(), 0);
+ SmallVector<int> InsertMask(NumElts, UndefMaskElem);
+ for (unsigned I = 0; I < NumElts; I++) {
+ if (Mask[I] != UndefMaskElem)
+ InsertMask[Offset + I] = NumElts + I;
+ }
+ if (Offset != 0 ||
+ !isUndefVector(FirstInsert->getOperand(0), InsertMask)) {
for (unsigned I = 0; I < NumElts; I++) {
- if (Mask[I] != UndefMaskElem)
- InsertMask[Offset + I] = NumElts + I;
+ if (InsertMask[I] == UndefMaskElem)
+ InsertMask[I] = I;
}
V = Builder.CreateShuffleVector(
if (IsIdentityMask(Mask, cast<FixedVectorType>(SV->getType())) ||
SV->isZeroEltSplat())
break;
- bool IsOp1Undef = isUndefVector(SV->getOperand(0));
- bool IsOp2Undef = isUndefVector(SV->getOperand(1));
+ bool IsOp1Undef = isUndefVector(SV->getOperand(0), Mask);
+ bool IsOp2Undef = isUndefVector(SV->getOperand(1), Mask);
if (!IsOp1Undef && !IsOp2Undef)
break;
SmallVector<int> ShuffleMask(SV->getShuffleMask().begin(),
&CombineMasks](Value *V1, Value *V2,
ArrayRef<int> Mask) -> Value * {
assert(V1 && "Expected at least one vector value.");
- if (V2 && !isUndefVector(V2)) {
+ if (V2 && !isUndefVector(V2, Mask)) {
// Peek through shuffles.
Value *Op1 = V1;
Value *Op2 = V2;
if (SV1->getOperand(0)->getType() ==
SV2->getOperand(0)->getType() &&
SV1->getOperand(0)->getType() != SV1->getType() &&
- isUndefVector(SV1->getOperand(1)) &&
- isUndefVector(SV2->getOperand(1))) {
+ isUndefVector(SV1->getOperand(1), CombinedMask1) &&
+ isUndefVector(SV2->getOperand(1), CombinedMask2)) {
Op1 = SV1->getOperand(0);
Op2 = SV2->getOperand(0);
SmallVector<int> ShuffleMask1(SV1->getShuffleMask().begin(),
; CHECK-NEXT: [[TMP5:%.*]] = select <4 x i1> [[TMP4]], <4 x float> zeroinitializer, <4 x float> zeroinitializer
; CHECK-NEXT: [[TMP6:%.*]] = fadd <4 x float> [[TMP5]], zeroinitializer
; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <4 x float> [[TMP6]], <4 x float> poison, <2 x i32> <i32 0, i32 1>
-; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <2 x float> zeroinitializer, <2 x float> [[TMP7]], <2 x i32> <i32 2, i32 3>
-; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <4 x float> [[TMP6]], <4 x float> poison, <2 x i32> <i32 2, i32 3>
-; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <2 x float> zeroinitializer, <2 x float> [[TMP9]], <2 x i32> <i32 2, i32 3>
-; CHECK-NEXT: [[DOTFCA_0_INSERT:%.*]] = insertvalue { <2 x float>, <2 x float> } zeroinitializer, <2 x float> [[TMP8]], 0
-; CHECK-NEXT: [[DOTFCA_1_INSERT:%.*]] = insertvalue { <2 x float>, <2 x float> } [[DOTFCA_0_INSERT]], <2 x float> [[TMP10]], 1
+; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <4 x float> [[TMP6]], <4 x float> poison, <2 x i32> <i32 2, i32 3>
+; CHECK-NEXT: [[DOTFCA_0_INSERT:%.*]] = insertvalue { <2 x float>, <2 x float> } zeroinitializer, <2 x float> [[TMP7]], 0
+; CHECK-NEXT: [[DOTFCA_1_INSERT:%.*]] = insertvalue { <2 x float>, <2 x float> } [[DOTFCA_0_INSERT]], <2 x float> [[TMP8]], 1
; CHECK-NEXT: ret { <2 x float>, <2 x float> } zeroinitializer
;
entry: