[llvm] [SLPVectorizer] Handle undef values in reused shuffle masks (PR #219662)
Oscar Priego via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 29 10:15:58 PDT 2026
https://github.com/Opriego updated https://github.com/llvm/llvm-project/pull/219662
>From a5ca745b9f38945284baf125f7eef020d0e184ae Mon Sep 17 00:00:00 2001
From: Oscar Priego Verdugo <oscar.priegov at gmail.com>
Date: Sat, 29 Aug 2026 03:33:47 -0600
Subject: [PATCH] [SLPVectorizer] Handle undef values in reused shuffle masks
---
.../Transforms/Vectorize/SLPVectorizer.cpp | 20 +++++++++++--
.../SLPVectorizer/X86/undef-reorder-reuse.ll | 30 +++++++++++++++++++
2 files changed, 48 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/undef-reorder-reuse.ll
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index a7eaef3701415..6a238e1c5d6ed 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -22863,17 +22863,33 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
// process to keep correct order.
return *Delayed;
}
+ const TreeEntry *FrontTE = Entries.front().front();
+ auto IsRepresentedByFrontTE = [&](Value *V) {
+ if (isa<PoisonValue>(V))
+ return true;
+ for (auto [I, Scalar] : enumerate(FrontTE->Scalars)) {
+ if (V != Scalar)
+ continue;
+ unsigned Lane = FrontTE->ReorderIndices.empty()
+ ? I
+ : FrontTE->ReorderIndices[I];
+ if (FrontTE->ReuseShuffleIndices.empty() ||
+ is_contained(FrontTE->ReuseShuffleIndices, Lane))
+ return true;
+ }
+ return false;
+ };
if (GatherShuffles.size() == 1 &&
*GatherShuffles.front() == TTI::SK_PermuteSingleSrc &&
(Entries.front().front()->isSame(E->Scalars) ||
- E->isSame(Entries.front().front()->Scalars))) {
+ E->isSame(Entries.front().front()->Scalars)) &&
+ all_of(E->Scalars, IsRepresentedByFrontTE)) {
// Perfect match in the graph, will reuse the previously vectorized
// node. Cost is 0.
LLVM_DEBUG(dbgs() << "SLP: perfect diamond match for gather bundle "
<< shortBundleName(E->Scalars, E->Idx) << ".\n");
// Restore the mask for previous partially matched values.
Mask.resize(E->Scalars.size());
- const TreeEntry *FrontTE = Entries.front().front();
if (FrontTE->ReorderIndices.empty() && E->ReorderIndices.empty() &&
((FrontTE->ReuseShuffleIndices.empty() &&
E->Scalars.size() == FrontTE->Scalars.size()) ||
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/undef-reorder-reuse.ll b/llvm/test/Transforms/SLPVectorizer/X86/undef-reorder-reuse.ll
new file mode 100644
index 0000000000000..93083a77b9982
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/undef-reorder-reuse.ll
@@ -0,0 +1,30 @@
+; RUN: opt -passes=slp-vectorizer -disable-output < %s
+
+; The undef lane matches a poison lane in a reordered, reused TreeEntry. It
+; must remain poison rather than being looked up as a concrete scalar lane.
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i8 @undef_in_reordered_reuse() {
+entry:
+ %load.0 = load i8, ptr null, align 1
+ %load.1 = load i8, ptr getelementptr inbounds nuw (i8, ptr null, i64 1), align 1
+ br label %entry.next
+
+entry.next:
+ br i1 false, label %if, label %merge
+
+if:
+ %phi.load.1 = phi i8 [ %load.1, %entry.next ]
+ %phi.load.0 = phi i8 [ %load.0, %entry.next ]
+ %phi.undef = phi i8 [ undef, %entry.next ]
+ br label %merge
+
+merge:
+ %phi.0 = phi i8 [ %phi.load.1, %if ], [ %load.1, %entry.next ]
+ %phi.1 = phi i8 [ %phi.load.0, %if ], [ %load.0, %entry.next ]
+ %phi.2 = phi i8 [ %phi.load.1, %if ], [ %load.1, %entry.next ]
+ %result = phi i8 [ %phi.undef, %if ], [ poison, %entry.next ]
+ ret i8 %result
+}
More information about the llvm-commits
mailing list