[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