aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@outlook.com>2024-04-26 11:22:52 -0700
committerAlexey Bataev <a.bataev@outlook.com>2024-04-26 11:49:12 -0700
commit79314c64d0f88fa4ccc1709dee373fdfb9a6ca49 (patch)
tree81ae28b49d2531837033a11512dc741872e76599
parent01d7dcfe5e3b261f587c05e33ffeecae7a11da80 (diff)
downloadllvm-79314c64d0f88fa4ccc1709dee373fdfb9a6ca49.zip
llvm-79314c64d0f88fa4ccc1709dee373fdfb9a6ca49.tar.gz
llvm-79314c64d0f88fa4ccc1709dee373fdfb9a6ca49.tar.bz2
[SLP]Fix PR90224: check that users of gep are all vectorized.
Before deleting extractelement instruction for vectorized GEP with external users, need to check that all users vectorized before deleting this extractelement.
-rw-r--r--llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp15
-rw-r--r--llvm/test/Transforms/SLPVectorizer/X86/gep-with-extractelement-many-users.ll26
2 files changed, 39 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index fbece8c..f62270f 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -8499,6 +8499,12 @@ public:
const TreeEntry *VE = R.getTreeEntry(V);
if (!CheckedExtracts.insert(V).second ||
!R.areAllUsersVectorized(cast<Instruction>(V), &VectorizedVals) ||
+ any_of(EE->users(),
+ [&](User *U) {
+ return isa<GetElementPtrInst>(U) &&
+ !R.areAllUsersVectorized(cast<Instruction>(U),
+ &VectorizedVals);
+ }) ||
(VE && VE != E))
continue;
std::optional<unsigned> EEIdx = getExtractIndex(EE);
@@ -11397,6 +11403,8 @@ public:
any_of(EI->users(), [&](User *U) {
const TreeEntry *UTE = R.getTreeEntry(U);
return !UTE || R.MultiNodeScalars.contains(U) ||
+ (isa<GetElementPtrInst>(U) &&
+ !R.areAllUsersVectorized(cast<Instruction>(U))) ||
count_if(R.VectorizableTree,
[&](const std::unique_ptr<TreeEntry> &TE) {
return any_of(TE->UserTreeIndices,
@@ -13329,8 +13337,11 @@ Value *BoUpSLP::vectorizeTree(
// Leave the GEPs as is, they are free in most cases and better to
// keep them as GEPs.
auto *CloneGEP = GEP->clone();
- CloneGEP->insertBefore(*Builder.GetInsertBlock(),
- Builder.GetInsertPoint());
+ if (isa<Instruction>(Vec))
+ CloneGEP->insertBefore(*Builder.GetInsertBlock(),
+ Builder.GetInsertPoint());
+ else
+ CloneGEP->insertBefore(GEP);
if (GEP->hasName())
CloneGEP->takeName(GEP);
Ex = CloneGEP;
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/gep-with-extractelement-many-users.ll b/llvm/test/Transforms/SLPVectorizer/X86/gep-with-extractelement-many-users.ll
new file mode 100644
index 0000000..37d1669
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/gep-with-extractelement-many-users.ll
@@ -0,0 +1,26 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-99999 < %s | FileCheck %s
+
+define void @test() {
+; CHECK-LABEL: define void @test() {
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[TMP0:%.*]] = extractelement <2 x ptr> zeroinitializer, i32 0
+; CHECK-NEXT: [[GETELEMENTPTR6:%.*]] = getelementptr i8, ptr [[TMP0]], i64 872
+; CHECK-NEXT: store double 0.000000e+00, ptr [[GETELEMENTPTR6]], align 8
+; CHECK-NEXT: br label [[BB9:%.*]]
+; CHECK: bb9:
+; CHECK-NEXT: [[TMP1:%.*]] = phi <2 x ptr> [ getelementptr (i8, <2 x ptr> zeroinitializer, <2 x i64> <i64 32, i64 872>), [[BB:%.*]] ]
+; CHECK-NEXT: ret void
+;
+bb:
+ %getelementptr = getelementptr i8, ptr null, i64 32
+ %0 = extractelement <2 x ptr> zeroinitializer, i32 0
+ %getelementptr6 = getelementptr i8, ptr %0, i64 872
+ store double 0.000000e+00, ptr %getelementptr6, align 8
+ br label %bb9
+
+bb9:
+ %phi10 = phi ptr [ %getelementptr, %bb ]
+ %phi11 = phi ptr [ %getelementptr6, %bb ]
+ ret void
+}