[SLP]Check if user node is same as other node and check operand order
Need to check if the user node is same as other node and check operand
order to prevent a compiler crash when trying to find matching gather
node with user nodes, having the same last instruction.
Fixes #131195
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 9c3992b..708dda9 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -14081,6 +14081,17 @@
}
return true;
};
+ auto CheckParentNodes = [&](const TreeEntry *User1, const TreeEntry *User2,
+ unsigned EdgeIdx) {
+ const TreeEntry *Ptr1 = User1;
+ while (Ptr1) {
+ unsigned Idx = Ptr1->UserTreeIndex.EdgeIdx;
+ Ptr1 = Ptr1->UserTreeIndex.UserTE;
+ if (Ptr1 == User2)
+ return Idx < EdgeIdx;
+ }
+ return false;
+ };
for (Value *V : VL) {
if (isConstant(V) || !VisitedValue.insert(V).second)
continue;
@@ -14121,6 +14132,9 @@
(TEUseEI.UserTE->Idx < UseEI.UserTE->Idx ||
HasGatherUser(TEUseEI.UserTE)))
continue;
+ // If the user node is the operand of the other user node - skip.
+ if (CheckParentNodes(TEUseEI.UserTE, UseEI.UserTE, UseEI.EdgeIdx))
+ continue;
}
// Check if the user node of the TE comes after user node of TEPtr,
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/user-node-with-same-last-instr.ll b/llvm/test/Transforms/SLPVectorizer/X86/user-node-with-same-last-instr.ll
new file mode 100644
index 0000000..c660710
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/user-node-with-same-last-instr.ll
@@ -0,0 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-99999 < %s | FileCheck %s
+
+define void @wombat(i32 %arg) {
+; CHECK-LABEL: define void @wombat(
+; CHECK-SAME: i32 [[ARG:%.*]]) {
+; CHECK-NEXT: [[BB:.*:]]
+; CHECK-NEXT: br label %[[BB1:.*]]
+; CHECK: [[BB1]]:
+; CHECK-NEXT: br i1 false, label %[[BB2:.*]], label %[[BB5:.*]]
+; CHECK: [[BB2]]:
+; CHECK-NEXT: [[TMP0:%.*]] = phi <2 x i32> [ [[TMP4:%.*]], %[[BB4:.*]] ], [ zeroinitializer, %[[BB1]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i32> <i32 poison, i32 1>, i32 [[ARG]], i32 0
+; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i32> [[TMP0]], [[TMP1]]
+; CHECK-NEXT: [[TMP3:%.*]] = or <2 x i32> [[TMP0]], [[TMP1]]
+; CHECK-NEXT: [[TMP4]] = shufflevector <2 x i32> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> <i32 0, i32 3>
+; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x i32> <i32 poison, i32 0>, i32 [[ARG]], i32 0
+; CHECK-NEXT: [[TMP6:%.*]] = sub <2 x i32> [[TMP0]], [[TMP5]]
+; CHECK-NEXT: [[TMP7:%.*]] = and <2 x i32> [[TMP0]], [[TMP5]]
+; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <2 x i32> [[TMP6]], <2 x i32> [[TMP7]], <2 x i32> <i32 0, i32 3>
+; CHECK-NEXT: br label %[[BB4]]
+; CHECK: [[BB4]]:
+; CHECK-NEXT: br i1 false, label %[[BB2]], label %[[BB5]]
+; CHECK: [[BB5]]:
+; CHECK-NEXT: [[TMP9:%.*]] = phi <2 x i32> [ zeroinitializer, %[[BB1]] ], [ [[TMP8]], %[[BB4]] ]
+; CHECK-NEXT: ret void
+;
+bb:
+ br label %bb1
+
+bb1:
+ br i1 false, label %bb2, label %bb5
+
+bb2:
+ %phi = phi i32 [ %or, %bb4 ], [ 0, %bb1 ]
+ %phi3 = phi i32 [ %sub, %bb4 ], [ 0, %bb1 ]
+ %or = or i32 %phi, 1
+ %and = and i32 0, %phi
+ %sub = sub i32 %phi3, %arg
+ br label %bb4
+
+bb4:
+ br i1 false, label %bb2, label %bb5
+
+bb5:
+ %phi6 = phi i32 [ 0, %bb1 ], [ %and, %bb4 ]
+ %phi7 = phi i32 [ 0, %bb1 ], [ %sub, %bb4 ]
+ ret void
+}