diff options
author | Alexey Bataev <a.bataev@outlook.com> | 2024-04-26 11:22:52 -0700 |
---|---|---|
committer | Alexey Bataev <a.bataev@outlook.com> | 2024-04-26 11:49:12 -0700 |
commit | 79314c64d0f88fa4ccc1709dee373fdfb9a6ca49 (patch) | |
tree | 81ae28b49d2531837033a11512dc741872e76599 | |
parent | 01d7dcfe5e3b261f587c05e33ffeecae7a11da80 (diff) | |
download | llvm-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.cpp | 15 | ||||
-rw-r--r-- | llvm/test/Transforms/SLPVectorizer/X86/gep-with-extractelement-many-users.ll | 26 |
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 +} |