[llvm-branch-commits] [llvm] release/23.x: [SLP]Fix crash in canBuildSplitNode on struct-typed scalars (PR #221722)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Sep 7 06:01:44 PDT 2026


https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/221722

Backport 42b846980eeacd8052d7a463e1aea8bb91aff248

Requested by: @nikic

>From 6dfe1677ab8dffbc6ec13d53a1e0215d75147689 Mon Sep 17 00:00:00 2001
From: Alexey Bataev <a.bataev at outlook.com>
Date: Mon, 7 Sep 2026 08:52:57 -0400
Subject: [PATCH] [SLP]Fix crash in canBuildSplitNode on struct-typed scalars

Split nodes require plain vector types for the cost model and codegen,
but getWidenedType on a struct scalar type returns a struct-of-vectors,
so the cast<VectorType> asserted. Bail out on struct-typed scalars, they
are not supported.

Fixes #221715

Reviewers:

Pull Request: https://github.com/llvm/llvm-project/pull/221721

(cherry picked from commit 42b846980eeacd8052d7a463e1aea8bb91aff248)
---
 .../Transforms/Vectorize/SLPVectorizer.cpp    |  3 +
 .../X86/split-node-struct-type.ll             | 67 +++++++++++++++++++
 2 files changed, 70 insertions(+)
 create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/split-node-struct-type.ll

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 3cba5769e0047..0c4d92085029f 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -11753,6 +11753,9 @@ bool BoUpSLP::canBuildSplitNode(ArrayRef<Value *> VL,
   if (VL.size() <= SmallNodeSize || TTI->preferAlternateOpcodeVectorization() ||
       !SplitAlternateInstructions)
     return false;
+  // Split vectorization of struct types is not supported.
+  if (isa<StructType>(getValueType(VL.front(), SLPReVec)))
+    return false;
 
   // Check if this is a duplicate of another split entry.
   LLVM_DEBUG(dbgs() << "SLP: \tChecking bundle: " << *LocalState.getMainOp()
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/split-node-struct-type.ll b/llvm/test/Transforms/SLPVectorizer/X86/split-node-struct-type.ll
new file mode 100644
index 0000000000000..8f9f8500b7208
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/split-node-struct-type.ll
@@ -0,0 +1,67 @@
+; 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 < %s | FileCheck %s
+
+declare { ptr, i64 } @foo()
+
+define { ptr, i64 } @test({ ptr, i64 } %arg, ptr %p) {
+; CHECK-LABEL: define { ptr, i64 } @test(
+; CHECK-SAME: { ptr, i64 } [[ARG:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[BBL:.*:]]
+; CHECK-NEXT:    br i1 false, label %[[BBL8:.*]], label %[[BBL1:.*]]
+; CHECK:       [[BBL1]]:
+; CHECK-NEXT:    [[INSERTVALUE:%.*]] = insertvalue { ptr, i64 } zeroinitializer, i64 0, 1
+; CHECK-NEXT:    [[INSERTVALUE2:%.*]] = insertvalue { ptr, i64 } zeroinitializer, i64 0, 1
+; CHECK-NEXT:    [[INSERTVALUE3:%.*]] = insertvalue { ptr, i64 } zeroinitializer, i64 0, 1
+; CHECK-NEXT:    [[INSERTVALUE4:%.*]] = insertvalue { ptr, i64 } zeroinitializer, i64 0, 1
+; CHECK-NEXT:    [[INSERTVALUE5:%.*]] = insertvalue { ptr, i64 } zeroinitializer, i64 0, 1
+; CHECK-NEXT:    [[CALL:%.*]] = call { ptr, i64 } @foo()
+; CHECK-NEXT:    [[CALL6:%.*]] = call { ptr, i64 } @foo()
+; CHECK-NEXT:    [[CALL7:%.*]] = call { ptr, i64 } @foo()
+; CHECK-NEXT:    br label %[[BBL11:.*]]
+; CHECK:       [[BBL8]]:
+; CHECK-NEXT:    [[LOAD:%.*]] = load volatile { ptr, i64 }, ptr [[P]], align 8
+; CHECK-NEXT:    [[LOAD9:%.*]] = load { ptr, i64 }, ptr [[P]], align 8
+; CHECK-NEXT:    [[LOAD10:%.*]] = load { ptr, i64 }, ptr [[P]], align 8
+; CHECK-NEXT:    br label %[[BBL11]]
+; CHECK:       [[BBL11]]:
+; CHECK-NEXT:    [[PHI:%.*]] = phi { ptr, i64 } [ [[CALL6]], %[[BBL1]] ], [ zeroinitializer, %[[BBL8]] ]
+; CHECK-NEXT:    [[PHI12:%.*]] = phi { ptr, i64 } [ [[INSERTVALUE5]], %[[BBL1]] ], [ zeroinitializer, %[[BBL8]] ]
+; CHECK-NEXT:    [[PHI13:%.*]] = phi { ptr, i64 } [ [[INSERTVALUE3]], %[[BBL1]] ], [ [[LOAD9]], %[[BBL8]] ]
+; CHECK-NEXT:    [[PHI14:%.*]] = phi { ptr, i64 } [ [[INSERTVALUE]], %[[BBL1]] ], [ [[ARG]], %[[BBL8]] ]
+; CHECK-NEXT:    [[PHI15:%.*]] = phi { ptr, i64 } [ [[INSERTVALUE2]], %[[BBL1]] ], [ [[LOAD]], %[[BBL8]] ]
+; CHECK-NEXT:    [[PHI16:%.*]] = phi { ptr, i64 } [ [[INSERTVALUE4]], %[[BBL1]] ], [ [[LOAD10]], %[[BBL8]] ]
+; CHECK-NEXT:    [[PHI17:%.*]] = phi { ptr, i64 } [ [[CALL]], %[[BBL1]] ], [ zeroinitializer, %[[BBL8]] ]
+; CHECK-NEXT:    [[PHI18:%.*]] = phi { ptr, i64 } [ [[CALL7]], %[[BBL1]] ], [ zeroinitializer, %[[BBL8]] ]
+; CHECK-NEXT:    ret { ptr, i64 } [[PHI18]]
+;
+bbl:
+  br i1 false, label %bbl8, label %bbl1
+
+bbl1:
+  %insertvalue = insertvalue { ptr, i64 } zeroinitializer, i64 0, 1
+  %insertvalue2 = insertvalue { ptr, i64 } zeroinitializer, i64 0, 1
+  %insertvalue3 = insertvalue { ptr, i64 } zeroinitializer, i64 0, 1
+  %insertvalue4 = insertvalue { ptr, i64 } zeroinitializer, i64 0, 1
+  %insertvalue5 = insertvalue { ptr, i64 } zeroinitializer, i64 0, 1
+  %call = call { ptr, i64 } @foo()
+  %call6 = call { ptr, i64 } @foo()
+  %call7 = call { ptr, i64 } @foo()
+  br label %bbl11
+
+bbl8:
+  %load = load volatile { ptr, i64 }, ptr %p, align 8
+  %load9 = load { ptr, i64 }, ptr %p, align 8
+  %load10 = load { ptr, i64 }, ptr %p, align 8
+  br label %bbl11
+
+bbl11:
+  %phi = phi { ptr, i64 } [ %call6, %bbl1 ], [ zeroinitializer, %bbl8 ]
+  %phi12 = phi { ptr, i64 } [ %insertvalue5, %bbl1 ], [ zeroinitializer, %bbl8 ]
+  %phi13 = phi { ptr, i64 } [ %insertvalue3, %bbl1 ], [ %load9, %bbl8 ]
+  %phi14 = phi { ptr, i64 } [ %insertvalue, %bbl1 ], [ %arg, %bbl8 ]
+  %phi15 = phi { ptr, i64 } [ %insertvalue2, %bbl1 ], [ %load, %bbl8 ]
+  %phi16 = phi { ptr, i64 } [ %insertvalue4, %bbl1 ], [ %load10, %bbl8 ]
+  %phi17 = phi { ptr, i64 } [ %call, %bbl1 ], [ zeroinitializer, %bbl8 ]
+  %phi18 = phi { ptr, i64 } [ %call7, %bbl1 ], [ zeroinitializer, %bbl8 ]
+  ret { ptr, i64 } %phi18
+}



More information about the llvm-branch-commits mailing list