Skip to content

Commit ec06df9

Browse files
committed
[SLP]Fix PR57447: Assertion `!getTreeEntry(V) && "Scalar already in tree!"' failed.
The pointer operands for the ScatterVectorize node may contain non-instruction values and they are not checked for "already being vectorized". Need to check that such pointers are already vectorized and gather them instead of trying to build vectorize node to avoid compiler crash. Differential Revision: https://reviews.llvm.org/D132949
1 parent 893f5e9 commit ec06df9

File tree

2 files changed

+65
-10
lines changed

2 files changed

+65
-10
lines changed

llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4701,10 +4701,12 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
47014701
};
47024702
SmallVector<unsigned> SortedIndices;
47034703
BasicBlock *BB = nullptr;
4704+
bool IsScatterVectorizeUserTE =
4705+
UserTreeIdx.UserTE &&
4706+
UserTreeIdx.UserTE->State == TreeEntry::ScatterVectorize;
47044707
bool AreAllSameInsts =
47054708
(S.getOpcode() && allSameBlock(VL)) ||
4706-
(S.OpValue->getType()->isPointerTy() && UserTreeIdx.UserTE &&
4707-
UserTreeIdx.UserTE->State == TreeEntry::ScatterVectorize &&
4709+
(S.OpValue->getType()->isPointerTy() && IsScatterVectorizeUserTE &&
47084710
VL.size() > 2 &&
47094711
all_of(VL,
47104712
[&BB](Value *V) {
@@ -4765,10 +4767,9 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
47654767

47664768
// Check that none of the instructions in the bundle are already in the tree.
47674769
for (Value *V : VL) {
4768-
auto *I = dyn_cast<Instruction>(V);
4769-
if (!I)
4770+
if (!IsScatterVectorizeUserTE && !isa<Instruction>(V))
47704771
continue;
4771-
if (getTreeEntry(I)) {
4772+
if (getTreeEntry(V)) {
47724773
LLVM_DEBUG(dbgs() << "SLP: The instruction (" << *V
47734774
<< ") is already in tree.\n");
47744775
if (TryToFindDuplicates(S))
@@ -5218,19 +5219,16 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
52185219
}
52195220
}
52205221

5221-
bool IsScatterUser =
5222-
UserTreeIdx.UserTE &&
5223-
UserTreeIdx.UserTE->State == TreeEntry::ScatterVectorize;
52245222
// We don't combine GEPs with non-constant indexes.
52255223
Type *Ty1 = VL0->getOperand(1)->getType();
52265224
for (Value *V : VL) {
52275225
auto *I = dyn_cast<GetElementPtrInst>(V);
52285226
if (!I)
52295227
continue;
52305228
auto *Op = I->getOperand(1);
5231-
if ((!IsScatterUser && !isa<ConstantInt>(Op)) ||
5229+
if ((!IsScatterVectorizeUserTE && !isa<ConstantInt>(Op)) ||
52325230
(Op->getType() != Ty1 &&
5233-
((IsScatterUser && !isa<ConstantInt>(Op)) ||
5231+
((IsScatterVectorizeUserTE && !isa<ConstantInt>(Op)) ||
52345232
Op->getType()->getScalarSizeInBits() >
52355233
DL->getIndexSizeInBits(
52365234
V->getType()->getPointerAddressSpace())))) {
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -S -slp-vectorizer < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=skylake -slp-threshold=-12 | FileCheck %s
3+
4+
define void @test(i1 %c, ptr %arg) {
5+
; CHECK-LABEL: @test(
6+
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
7+
; CHECK: if:
8+
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x ptr> poison, ptr [[ARG:%.*]], i32 0
9+
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x ptr> [[TMP1]], <4 x ptr> poison, <4 x i32> zeroinitializer
10+
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i8, <4 x ptr> [[SHUFFLE]], <4 x i64> <i64 32, i64 24, i64 8, i64 0>
11+
; CHECK-NEXT: [[TMP3:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[TMP2]], i32 8, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i64> undef)
12+
; CHECK-NEXT: br label [[JOIN:%.*]]
13+
; CHECK: else:
14+
; CHECK-NEXT: [[ARG_1:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 8
15+
; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x ptr> poison, ptr [[ARG]], i32 0
16+
; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x ptr> [[TMP4]], ptr [[ARG]], i32 1
17+
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i8, <2 x ptr> [[TMP5]], <2 x i64> <i64 32, i64 24>
18+
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x ptr> poison, ptr [[ARG]], i32 3
19+
; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <2 x ptr> [[TMP6]], <2 x ptr> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
20+
; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <4 x ptr> [[TMP7]], <4 x ptr> [[TMP8]], <4 x i32> <i32 4, i32 5, i32 2, i32 3>
21+
; CHECK-NEXT: [[TMP10:%.*]] = insertelement <4 x ptr> [[TMP9]], ptr [[ARG_1]], i32 2
22+
; CHECK-NEXT: [[TMP11:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[TMP10]], i32 8, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i64> undef)
23+
; CHECK-NEXT: br label [[JOIN]]
24+
; CHECK: join:
25+
; CHECK-NEXT: [[TMP12:%.*]] = phi <4 x i64> [ [[TMP3]], [[IF]] ], [ [[TMP11]], [[ELSE]] ]
26+
; CHECK-NEXT: ret void
27+
;
28+
br i1 %c, label %if, label %else
29+
30+
if:
31+
%i2.0 = load i64, ptr %arg, align 8
32+
%arg2.1 = getelementptr inbounds i8, ptr %arg, i64 8
33+
%i2.1 = load i64, ptr %arg2.1, align 8
34+
%arg2.2 = getelementptr inbounds i8, ptr %arg, i64 24
35+
%i2.2 = load i64, ptr %arg2.2, align 8
36+
%arg2.3 = getelementptr inbounds i8, ptr %arg, i64 32
37+
%i2.3 = load i64, ptr %arg2.3, align 8
38+
br label %join
39+
40+
else:
41+
%i.0 = load i64, ptr %arg, align 8
42+
%arg.1 = getelementptr inbounds i8, ptr %arg, i64 8
43+
%i.1 = load i64, ptr %arg.1, align 8
44+
%arg.2 = getelementptr inbounds i8, ptr %arg, i64 24
45+
%i.2 = load i64, ptr %arg.2, align 8
46+
%arg.3 = getelementptr inbounds i8, ptr %arg, i64 32
47+
%i.3 = load i64, ptr %arg.3, align 8
48+
br label %join
49+
50+
join:
51+
%phi.3 = phi i64 [ %i2.3, %if ], [ %i.3, %else ]
52+
%phi.2 = phi i64 [ %i2.2, %if ], [ %i.2, %else ]
53+
%phi.1 = phi i64 [ %i2.1, %if ], [ %i.1, %else ]
54+
%phi.0 = phi i64 [ %i2.0, %if ], [ %i.0, %else ]
55+
ret void
56+
}
57+

0 commit comments

Comments
 (0)