diff options
-rw-r--r-- | llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp | 14 | ||||
-rw-r--r-- | llvm/test/Transforms/SLPVectorizer/X86/user-node-with-same-last-instr.ll | 49 |
2 files changed, 63 insertions, 0 deletions
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 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry( } 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 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry( (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 +} |