[llvm] [SLP]Fix crash on deleted main op of copyable state in reductions (PR #228806)

Alexey Bataev via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 3 18:48:37 PDT 2026


https://github.com/alexey-bataev created https://github.com/llvm/llvm-project/pull/228806

Vectorizing one group of reduced values can erase the main operation of
a later group's copyable state, leaving it with dropped operands.

Fixes #228768


>From b50be892a7f85a91da8fab65589b39c1eaf6e884 Mon Sep 17 00:00:00 2001
From: Alexey Bataev <a.bataev at outlook.com>
Date: Sat, 3 Oct 2026 18:48:25 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.7
---
 .../Transforms/Vectorize/SLPVectorizer.cpp    |  5 ++
 .../reduction-erased-copyable-cast-main-op.ll | 56 +++++++++++++++++++
 2 files changed, 61 insertions(+)
 create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/reduction-erased-copyable-cast-main-op.ll

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 0981c124e3aec..a03dfe49a85f1 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -32679,6 +32679,11 @@ class HorizontalReduction {
     for (unsigned I = 0, E = ReducedVals.size(); I < E; ++I) {
       ArrayRef<Value *> OrigReducedVals = ReducedVals[I];
       InstructionsState S = States[I];
+      // The main operation of a state with copyable elements may be deleted
+      // during previous vectorization attempts, the state is not usable then.
+      if (S && S.areInstructionsWithCopyableElements() &&
+          V.isDeleted(S.getMainOp()))
+        S = InstructionsState::invalid();
       SmallVector<Value *> Candidates;
       Candidates.reserve(2 * OrigReducedVals.size());
       SmallVector<Value *> TrackedToOrig;
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/reduction-erased-copyable-cast-main-op.ll b/llvm/test/Transforms/SLPVectorizer/X86/reduction-erased-copyable-cast-main-op.ll
new file mode 100644
index 0000000000000..ccc7f41977635
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/reduction-erased-copyable-cast-main-op.ll
@@ -0,0 +1,56 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
+
+; The tree of the reduced ands erases the reduced zexts, including the main
+; operation of the zext group with a copyable constant.
+define i64 @test(ptr %p) {
+; CHECK-LABEL: define i64 @test(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[V:%.*]] = load i8, ptr [[P]], align 1
+; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <4 x i8> poison, i8 [[V]], i64 0
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> poison, <4 x i32> zeroinitializer
+; CHECK-NEXT:    [[TMP2:%.*]] = and <4 x i8> [[TMP1]], <i8 1, i8 -1, i8 -1, i8 -1>
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x i8> [[TMP2]], i64 0
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i8 [[TMP3]] to i64
+; CHECK-NEXT:    [[Z2:%.*]] = zext i8 [[V]] to i64
+; CHECK-NEXT:    [[TMP5:%.*]] = mul <4 x i8> [[TMP2]], <i8 7, i8 7, i8 7, i8 1>
+; CHECK-NEXT:    [[TMP6:%.*]] = and <4 x i8> [[TMP5]], <i8 5, i8 5, i8 5, i8 -1>
+; CHECK-NEXT:    [[TMP7:%.*]] = zext <4 x i8> [[TMP6]] to <4 x i64>
+; CHECK-NEXT:    [[TMP8:%.*]] = mul <4 x i64> [[TMP7]], <i64 3, i64 2, i64 2, i64 3>
+; CHECK-NEXT:    [[TMP9:%.*]] = call i64 @llvm.vector.reduce.add.v4i64(<4 x i64> [[TMP8]])
+; CHECK-NEXT:    [[TMP10:%.*]] = mul i64 [[TMP4]], 2
+; CHECK-NEXT:    [[TMP11:%.*]] = mul i64 [[Z2]], 2
+; CHECK-NEXT:    [[OP_RDX5:%.*]] = add i64 [[TMP10]], [[TMP11]]
+; CHECK-NEXT:    [[OP_RDX6:%.*]] = add i64 [[OP_RDX5]], 1
+; CHECK-NEXT:    [[OP_RDX7:%.*]] = add i64 [[OP_RDX6]], [[TMP9]]
+; CHECK-NEXT:    ret i64 [[OP_RDX7]]
+;
+entry:
+  %v = load i8, ptr %p, align 1
+  %m = and i8 %v, 1
+  %z0 = zext i8 %m to i64
+  %mul0 = mul i64 %z0, 7
+  %a0 = and i64 %mul0, 5
+  %s0 = add i64 %a0, 1
+  %z1 = zext i8 %v to i64
+  %s1 = add i64 %s0, %z1
+  %z2 = zext i8 %v to i64
+  %s2 = add i64 %s1, %z2
+  %mul2 = mul i64 %z2, 7
+  %a2 = and i64 %mul2, 5
+  %s3 = add i64 %s2, %a2
+  %s4 = add i64 %s3, %z0
+  %s5 = add i64 %s4, %a0
+  %s6 = add i64 %s5, %z1
+  %mul1 = mul i64 %z1, 7
+  %a1 = and i64 %mul1, 5
+  %s7 = add i64 %s6, %a1
+  %s8 = add i64 %s7, %z2
+  %s9 = add i64 %s8, %a2
+  %s10 = add i64 %s9, %z0
+  %s11 = add i64 %s10, %a0
+  %s12 = add i64 %s11, %z1
+  %s13 = add i64 %s12, %a1
+  ret i64 %s13
+}



More information about the llvm-commits mailing list