Skip to content

Commit 3cc15e2

Browse files
committed
[SLP] Fix assert from non-constant index in insertelement
A call to getInsertIndex() in getTreeCost() is returning None, which causes an assert because a non-constant index value for insertelement was not expected. This case occurs when the insertelement index value is defined with a PHI. Differential Revision: https://reviews.llvm.org/D120223
1 parent b3f4535 commit 3cc15e2

File tree

2 files changed

+63
-30
lines changed

2 files changed

+63
-30
lines changed

llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5919,39 +5919,41 @@ InstructionCost BoUpSLP::getTreeCost(ArrayRef<Value *> VectorizedVals) {
59195919
// to detect it as a final shuffled/identity match.
59205920
if (auto *VU = dyn_cast_or_null<InsertElementInst>(EU.User)) {
59215921
if (auto *FTy = dyn_cast<FixedVectorType>(VU->getType())) {
5922-
unsigned InsertIdx = *getInsertIndex(VU);
5923-
auto *It = find_if(FirstUsers, [VU](Value *V) {
5924-
return areTwoInsertFromSameBuildVector(VU,
5925-
cast<InsertElementInst>(V));
5926-
});
5927-
int VecId = -1;
5928-
if (It == FirstUsers.end()) {
5929-
VF.push_back(FTy->getNumElements());
5930-
ShuffleMask.emplace_back(VF.back(), UndefMaskElem);
5931-
// Find the insertvector, vectorized in tree, if any.
5932-
Value *Base = VU;
5933-
while (isa<InsertElementInst>(Base)) {
5934-
// Build the mask for the vectorized insertelement instructions.
5935-
if (const TreeEntry *E = getTreeEntry(Base)) {
5936-
VU = cast<InsertElementInst>(Base);
5937-
do {
5938-
int Idx = E->findLaneForValue(Base);
5939-
ShuffleMask.back()[Idx] = Idx;
5940-
Base = cast<InsertElementInst>(Base)->getOperand(0);
5941-
} while (E == getTreeEntry(Base));
5942-
break;
5922+
Optional<unsigned> InsertIdx = getInsertIndex(VU);
5923+
if (InsertIdx) {
5924+
auto *It = find_if(FirstUsers, [VU](Value *V) {
5925+
return areTwoInsertFromSameBuildVector(VU,
5926+
cast<InsertElementInst>(V));
5927+
});
5928+
int VecId = -1;
5929+
if (It == FirstUsers.end()) {
5930+
VF.push_back(FTy->getNumElements());
5931+
ShuffleMask.emplace_back(VF.back(), UndefMaskElem);
5932+
// Find the insertvector, vectorized in tree, if any.
5933+
Value *Base = VU;
5934+
while (isa<InsertElementInst>(Base)) {
5935+
// Build the mask for the vectorized insertelement instructions.
5936+
if (const TreeEntry *E = getTreeEntry(Base)) {
5937+
VU = cast<InsertElementInst>(Base);
5938+
do {
5939+
int Idx = E->findLaneForValue(Base);
5940+
ShuffleMask.back()[Idx] = Idx;
5941+
Base = cast<InsertElementInst>(Base)->getOperand(0);
5942+
} while (E == getTreeEntry(Base));
5943+
break;
5944+
}
5945+
Base = cast<InsertElementInst>(Base)->getOperand(0);
59435946
}
5944-
Base = cast<InsertElementInst>(Base)->getOperand(0);
5947+
FirstUsers.push_back(VU);
5948+
DemandedElts.push_back(APInt::getZero(VF.back()));
5949+
VecId = FirstUsers.size() - 1;
5950+
} else {
5951+
VecId = std::distance(FirstUsers.begin(), It);
59455952
}
5946-
FirstUsers.push_back(VU);
5947-
DemandedElts.push_back(APInt::getZero(VF.back()));
5948-
VecId = FirstUsers.size() - 1;
5949-
} else {
5950-
VecId = std::distance(FirstUsers.begin(), It);
5953+
ShuffleMask[VecId][*InsertIdx] = EU.Lane;
5954+
DemandedElts[VecId].setBit(*InsertIdx);
5955+
continue;
59515956
}
5952-
ShuffleMask[VecId][InsertIdx] = EU.Lane;
5953-
DemandedElts[VecId].setBit(InsertIdx);
5954-
continue;
59555957
}
59565958
}
59575959

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -slp-vectorizer -slp-max-vf=2 -slp-min-reg-size=32 -S < %s | FileCheck %s
3+
4+
; It is possible to compute the tree cost for an insertelement that does not
5+
; have a constant index when the index is a PHI. Check if getInsertIndex
6+
; returns None.
7+
8+
define void @test() local_unnamed_addr {
9+
; CHECK-LABEL: @test(
10+
; CHECK-NEXT: entry:
11+
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
12+
; CHECK: for.cond.cleanup:
13+
; CHECK-NEXT: unreachable
14+
; CHECK: for.body:
15+
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ poison, [[FOR_BODY]] ]
16+
; CHECK-NEXT: [[J:%.*]] = phi i32 [ poison, [[ENTRY]] ], [ 0, [[FOR_BODY]] ]
17+
; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x i32> poison, i32 poison, i32 [[I]]
18+
; CHECK-NEXT: br i1 poison, label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
19+
;
20+
entry:
21+
br label %for.body
22+
23+
for.cond.cleanup:
24+
unreachable
25+
26+
for.body:
27+
%i = phi i32 [ 0, %entry ], [ poison, %for.body ]
28+
%j = phi i32 [ poison, %entry ], [ 0, %for.body ]
29+
%0 = insertelement <4 x i32> poison, i32 poison, i32 %i
30+
br i1 poison, label %for.cond.cleanup, label %for.body
31+
}

0 commit comments

Comments
 (0)