Skip to content

Commit c9cea24

Browse files
committed
[SLP] Check if the user node has state before trying getting main instruction/opcode
Need to check if the parent node has state to prevent compiler crashes. Fixes #150479
1 parent 8952225 commit c9cea24

File tree

2 files changed

+93
-33
lines changed

2 files changed

+93
-33
lines changed

llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6861,7 +6861,7 @@ BoUpSLP::getReorderingData(const TreeEntry &TE, bool TopToBottom,
68616861
return std::move(ResOrder);
68626862
}
68636863
if (TE.State == TreeEntry::StridedVectorize && !TopToBottom &&
6864-
(!TE.UserTreeIndex ||
6864+
(!TE.UserTreeIndex || !TE.UserTreeIndex.UserTE->hasState() ||
68656865
!Instruction::isBinaryOp(TE.UserTreeIndex.UserTE->getOpcode())) &&
68666866
(TE.ReorderIndices.empty() || isReverseOrder(TE.ReorderIndices)))
68676867
return std::nullopt;
@@ -15704,7 +15704,8 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
1570415704
const BasicBlock *TEInsertBlock = nullptr;
1570515705
// Main node of PHI entries keeps the correct order of operands/incoming
1570615706
// blocks.
15707-
if (auto *PHI = dyn_cast<PHINode>(TEUseEI.UserTE->getMainOp());
15707+
if (auto *PHI = dyn_cast_or_null<PHINode>(
15708+
TEUseEI.UserTE->hasState() ? TEUseEI.UserTE->getMainOp() : nullptr);
1570815709
PHI && TEUseEI.UserTE->State != TreeEntry::SplitVectorize) {
1570915710
TEInsertBlock = PHI->getIncomingBlock(TEUseEI.EdgeIdx);
1571015711
TEInsertPt = TEInsertBlock->getTerminator();
@@ -15803,7 +15804,8 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
1580315804
"Expected only single user of a gather node.");
1580415805
const EdgeInfo &UseEI = TEPtr->UserTreeIndex;
1580515806

15806-
PHINode *UserPHI = UseEI.UserTE->State != TreeEntry::SplitVectorize
15807+
PHINode *UserPHI = (UseEI.UserTE->State != TreeEntry::SplitVectorize &&
15808+
UseEI.UserTE->hasState())
1580715809
? dyn_cast<PHINode>(UseEI.UserTE->getMainOp())
1580815810
: nullptr;
1580915811
Instruction *InsertPt =
@@ -15816,7 +15818,8 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
1581615818
TEUseEI.UserTE->isAltShuffle()) &&
1581715819
all_of(TEUseEI.UserTE->Scalars, isUsedOutsideBlock)) {
1581815820
if (UseEI.UserTE->State != TreeEntry::Vectorize ||
15819-
(UseEI.UserTE->getOpcode() == Instruction::PHI &&
15821+
(UseEI.UserTE->hasState() &&
15822+
UseEI.UserTE->getOpcode() == Instruction::PHI &&
1582015823
!UseEI.UserTE->isAltShuffle()) ||
1582115824
!all_of(UseEI.UserTE->Scalars, isUsedOutsideBlock))
1582215825
continue;
@@ -16438,24 +16441,31 @@ Instruction &BoUpSLP::getLastInstructionInBundle(const TreeEntry *E) {
1643816441
// Get the basic block this bundle is in. All instructions in the bundle
1643916442
// should be in this block (except for extractelement-like instructions with
1644016443
// constant indices or gathered loads or copyables).
16441-
auto *Front = E->getMainOp();
16444+
Instruction *Front;
16445+
unsigned Opcode;
16446+
if (E->hasState()) {
16447+
Front = E->getMainOp();
16448+
Opcode = E->getOpcode();
16449+
} else {
16450+
Front = cast<Instruction>(*find_if(E->Scalars, IsaPred<Instruction>));
16451+
Opcode = Front->getOpcode();
16452+
}
1644216453
auto *BB = Front->getParent();
16443-
assert(((GatheredLoadsEntriesFirst.has_value() &&
16444-
E->getOpcode() == Instruction::Load && E->isGather() &&
16445-
E->Idx < *GatheredLoadsEntriesFirst) ||
16446-
E->State == TreeEntry::SplitVectorize || E->hasCopyableElements() ||
16447-
all_of(E->Scalars,
16448-
[=](Value *V) -> bool {
16449-
if (E->getOpcode() == Instruction::GetElementPtr &&
16450-
!isa<GetElementPtrInst>(V))
16451-
return true;
16452-
auto *I = dyn_cast<Instruction>(V);
16453-
return !I || !E->getMatchingMainOpOrAltOp(I) ||
16454-
I->getParent() == BB ||
16455-
isVectorLikeInstWithConstOps(I);
16456-
})) &&
16457-
"Expected gathered loads or GEPs or instructions from same basic "
16458-
"block.");
16454+
assert(
16455+
((GatheredLoadsEntriesFirst.has_value() && Opcode == Instruction::Load &&
16456+
E->isGather() && E->Idx < *GatheredLoadsEntriesFirst) ||
16457+
E->State == TreeEntry::SplitVectorize || E->hasCopyableElements() ||
16458+
all_of(E->Scalars,
16459+
[=](Value *V) -> bool {
16460+
if (Opcode == Instruction::GetElementPtr &&
16461+
!isa<GetElementPtrInst>(V))
16462+
return true;
16463+
auto *I = dyn_cast<Instruction>(V);
16464+
return !I || !E->getMatchingMainOpOrAltOp(I) ||
16465+
I->getParent() == BB || isVectorLikeInstWithConstOps(I);
16466+
})) &&
16467+
"Expected gathered loads or GEPs or instructions from same basic "
16468+
"block.");
1645916469

1646016470
auto FindLastInst = [&]() {
1646116471
Instruction *LastInst = Front;
@@ -16470,13 +16480,13 @@ Instruction &BoUpSLP::getLastInstructionInBundle(const TreeEntry *E) {
1647016480
LastInst = I;
1647116481
continue;
1647216482
}
16473-
assert(((E->getOpcode() == Instruction::GetElementPtr &&
16483+
assert(((Opcode == Instruction::GetElementPtr &&
1647416484
!isa<GetElementPtrInst>(I)) ||
1647516485
E->State == TreeEntry::SplitVectorize ||
1647616486
(isVectorLikeInstWithConstOps(LastInst) &&
1647716487
isVectorLikeInstWithConstOps(I)) ||
1647816488
(GatheredLoadsEntriesFirst.has_value() &&
16479-
E->getOpcode() == Instruction::Load && E->isGather() &&
16489+
Opcode == Instruction::Load && E->isGather() &&
1648016490
E->Idx < *GatheredLoadsEntriesFirst)) &&
1648116491
"Expected vector-like or non-GEP in GEP node insts only.");
1648216492
if (!DT->isReachableFromEntry(LastInst->getParent())) {
@@ -16512,11 +16522,11 @@ Instruction &BoUpSLP::getLastInstructionInBundle(const TreeEntry *E) {
1651216522
FirstInst = I;
1651316523
continue;
1651416524
}
16515-
assert(((E->getOpcode() == Instruction::GetElementPtr &&
16516-
!isa<GetElementPtrInst>(I)) ||
16517-
(isVectorLikeInstWithConstOps(FirstInst) &&
16518-
isVectorLikeInstWithConstOps(I))) &&
16519-
"Expected vector-like or non-GEP in GEP node insts only.");
16525+
assert(((Opcode == Instruction::GetElementPtr &&
16526+
!isa<GetElementPtrInst>(I)) ||
16527+
(isVectorLikeInstWithConstOps(FirstInst) &&
16528+
isVectorLikeInstWithConstOps(I))) &&
16529+
"Expected vector-like or non-GEP in GEP node insts only.");
1652016530
if (!DT->isReachableFromEntry(FirstInst->getParent())) {
1652116531
FirstInst = I;
1652216532
continue;
@@ -16554,7 +16564,7 @@ Instruction &BoUpSLP::getLastInstructionInBundle(const TreeEntry *E) {
1655416564
// Set insertpoint for gathered loads to the very first load.
1655516565
if (GatheredLoadsEntriesFirst.has_value() &&
1655616566
E->Idx >= *GatheredLoadsEntriesFirst && !E->isGather() &&
16557-
E->getOpcode() == Instruction::Load) {
16567+
Opcode == Instruction::Load) {
1655816568
Res = FindFirstInst();
1655916569
EntryToLastInstruction.try_emplace(E, Res);
1656016570
return *Res;
@@ -16586,7 +16596,7 @@ Instruction &BoUpSLP::getLastInstructionInBundle(const TreeEntry *E) {
1658616596
};
1658716597
const ScheduleBundle *Bundle = FindScheduleBundle(E);
1658816598
if (!E->isGather() && !Bundle) {
16589-
if ((E->getOpcode() == Instruction::GetElementPtr &&
16599+
if ((Opcode == Instruction::GetElementPtr &&
1659016600
any_of(E->Scalars,
1659116601
[](Value *V) {
1659216602
return !isa<GetElementPtrInst>(V) && isa<Instruction>(V);
@@ -21001,9 +21011,10 @@ void BoUpSLP::computeMinimumValueSizes() {
2100121011
if (!isa<CastInst, BinaryOperator, FreezeInst, PHINode,
2100221012
SelectInst>(U) ||
2100321013
isa<SIToFPInst, UIToFPInst>(U) ||
21004-
!isa<CastInst, BinaryOperator, FreezeInst, PHINode,
21005-
SelectInst>(UserTE->getMainOp()) ||
21006-
isa<SIToFPInst, UIToFPInst>(UserTE->getMainOp()))
21014+
(UserTE->hasState() &&
21015+
(!isa<CastInst, BinaryOperator, FreezeInst, PHINode,
21016+
SelectInst>(UserTE->getMainOp()) ||
21017+
isa<SIToFPInst, UIToFPInst>(UserTE->getMainOp()))))
2100721018
return true;
2100821019
unsigned UserTESz = DL->getTypeSizeInBits(
2100921020
UserTE->Scalars.front()->getType());
@@ -21253,6 +21264,7 @@ void BoUpSLP::computeMinimumValueSizes() {
2125321264
NodeIdx < VectorizableTree.size() &&
2125421265
VectorizableTree[NodeIdx]->UserTreeIndex &&
2125521266
VectorizableTree[NodeIdx]->UserTreeIndex.EdgeIdx == 0 &&
21267+
VectorizableTree[NodeIdx]->UserTreeIndex.UserTE->hasState() &&
2125621268
VectorizableTree[NodeIdx]->UserTreeIndex.UserTE->getOpcode() ==
2125721269
Instruction::Trunc &&
2125821270
!VectorizableTree[NodeIdx]->UserTreeIndex.UserTE->isAltShuffle();
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
3+
4+
@g = global [128 x i8] zeroinitializer, align 16
5+
6+
define i64 @test() {
7+
; CHECK-LABEL: define i64 @test() {
8+
; CHECK-NEXT: [[ENTRY:.*:]]
9+
; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @g, align 8
10+
; CHECK-NEXT: br label %[[FUNC_154_EXIT_FUNC_146_EXIT_CRIT_EDGE_I:.*]]
11+
; CHECK: [[FUNC_154_EXIT_FUNC_146_EXIT_CRIT_EDGE_I]]:
12+
; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr getelementptr inbounds nuw (i8, ptr @g, i64 80), align 16
13+
; CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr getelementptr inbounds nuw (i8, ptr @g, i64 88), align 8
14+
; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr getelementptr inbounds nuw (i8, ptr @g, i64 32), align 16
15+
; CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @g, align 16
16+
; CHECK-NEXT: [[TMP5:%.*]] = load i64, ptr getelementptr inbounds nuw (i8, ptr @g, i64 8), align 8
17+
; CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr @g, align 16
18+
; CHECK-NEXT: [[TMP7:%.*]] = load i64, ptr getelementptr inbounds nuw (i8, ptr @g, i64 24), align 8
19+
; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP1]], [[TMP2]]
20+
; CHECK-NEXT: [[TMP9:%.*]] = xor i64 [[TMP8]], [[TMP3]]
21+
; CHECK-NEXT: [[TMP10:%.*]] = xor i64 [[TMP9]], [[TMP4]]
22+
; CHECK-NEXT: [[TMP11:%.*]] = xor i64 [[TMP10]], [[TMP5]]
23+
; CHECK-NEXT: [[TMP12:%.*]] = xor i64 [[TMP11]], [[TMP6]]
24+
; CHECK-NEXT: [[TMP13:%.*]] = xor i64 [[TMP12]], [[TMP7]]
25+
; CHECK-NEXT: [[TMP14:%.*]] = xor i64 [[TMP13]], [[TMP0]]
26+
; CHECK-NEXT: ret i64 [[TMP14]]
27+
;
28+
entry:
29+
%0 = load i64, ptr @g, align 8
30+
br label %func_154.exit.func_146.exit_crit_edge.i
31+
32+
func_154.exit.func_146.exit_crit_edge.i:
33+
%1 = load i64, ptr getelementptr inbounds nuw (i8, ptr @g, i64 80), align 16
34+
%2 = load i64, ptr getelementptr inbounds nuw (i8, ptr @g, i64 88), align 8
35+
%3 = load i64, ptr getelementptr inbounds nuw (i8, ptr @g, i64 32), align 16
36+
%4 = load i64, ptr @g, align 16
37+
%5 = load i64, ptr getelementptr inbounds nuw (i8, ptr @g, i64 8), align 8
38+
%6 = load i64, ptr @g, align 16
39+
%7 = load i64, ptr getelementptr inbounds nuw (i8, ptr @g, i64 24), align 8
40+
%8 = xor i64 %1, %2
41+
%9 = xor i64 %8, %3
42+
%10 = xor i64 %9, %4
43+
%11 = xor i64 %10, %5
44+
%12 = xor i64 %11, %6
45+
%13 = xor i64 %12, %7
46+
%14 = xor i64 %13, %0
47+
ret i64 %14
48+
}

0 commit comments

Comments
 (0)