[llvm] bdd1b0a - [SLP]Fix erasing reduced vals after partial shuffled-extract group merge
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 25 10:48:37 PDT 2026
Author: Alexey Bataev
Date: 2026-08-25T13:48:32-04:00
New Revision: bdd1b0aa73e75d6e45af1f6b0fee2275c68f2adb
URL: https://github.com/llvm/llvm-project/commit/bdd1b0aa73e75d6e45af1f6b0fee2275c68f2adb
DIFF: https://github.com/llvm/llvm-project/commit/bdd1b0aa73e75d6e45af1f6b0fee2275c68f2adb.diff
LOG: [SLP]Fix erasing reduced vals after partial shuffled-extract group merge
The merge copied only extractelements from the next reduced-values
group but skipped the whole group when collecting externally used
values, so a leftover reduced value could be erased while still used
by reduction ops. Merge only groups made solely of extractelements.
Fixes #218709
Reviewers:
Pull Request: https://github.com/llvm/llvm-project/pull/218734
Added:
llvm/test/Transforms/SLPVectorizer/X86/reduced-val-vectorized-in-tree.ll
Modified:
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index e548d205e6dcb..50d81058968d4 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -31099,9 +31099,14 @@ class HorizontalReduction {
TrackedToOrig.push_back(ReducedVal);
}
bool ShuffledExtracts = false;
- // Try to handle shuffled extractelements.
+ // Try to handle shuffled extractelements. Only pure extractelement
+ // groups can be merged: merged groups are skipped for external uses,
+ // and other values would be erased while still used by reduction ops.
if (S && S.getOpcode() == Instruction::ExtractElement &&
- !S.isAltShuffle() && I + 1 < E) {
+ !S.isAltShuffle() && I + 1 < E &&
+ all_of(ReducedVals[I + 1], [&](Value *RV) {
+ return isa<ExtractElementInst>(TrackedVals.at(RV));
+ })) {
SmallVector<Value *> CommonCandidates(Candidates);
for (Value *RV : ReducedVals[I + 1]) {
Value *RdxVal = TrackedVals.at(RV);
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/reduced-val-vectorized-in-tree.ll b/llvm/test/Transforms/SLPVectorizer/X86/reduced-val-vectorized-in-tree.ll
new file mode 100644
index 0000000000000..c4e23e6e4fa29
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/reduced-val-vectorized-in-tree.ll
@@ -0,0 +1,120 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=slp-vectorizer -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+
+define i64 @test(i64 %d, ptr %a) {
+; CHECK-LABEL: define i64 @test(
+; CHECK-SAME: i64 [[D:%.*]], ptr [[A:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A]], align 8
+; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i8, ptr [[TMP0]], i64 24
+; CHECK-NEXT: [[ARRAYIDX_2:%.*]] = getelementptr i8, ptr [[TMP0]], i64 40
+; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr [[ARRAYIDX]], align 8
+; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i64> poison, i64 [[D]], i64 0
+; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x i64> [[TMP2]], <2 x i64> poison, <2 x i32> zeroinitializer
+; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i64> [[TMP3]], <i64 0, i64 1>
+; CHECK-NEXT: [[TMP5:%.*]] = xor <2 x i64> [[TMP1]], [[TMP4]]
+; CHECK-NEXT: [[TMP6:%.*]] = or <2 x i64> [[TMP5]], splat (i64 1)
+; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x i64> [[TMP3]], <2 x i64> <i64 undef, i64 0>, <4 x i32> <i32 0, i32 0, i32 0, i32 3>
+; CHECK-NEXT: [[TMP8:%.*]] = or <4 x i64> <i64 0, i64 1, i64 1, i64 1>, [[TMP7]]
+; CHECK-NEXT: [[TMP9:%.*]] = load <4 x i64>, ptr [[ARRAYIDX_2]], align 8
+; CHECK-NEXT: [[TMP10:%.*]] = xor <4 x i64> [[TMP9]], [[TMP8]]
+; CHECK-NEXT: [[TMP11:%.*]] = add <4 x i64> [[TMP10]], splat (i64 1)
+; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <2 x i64> [[TMP6]], <2 x i64> poison, <6 x i32> <i32 0, i32 1, i32 poison, i32 poison, i32 poison, i32 poison>
+; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <4 x i64> [[TMP11]], <4 x i64> poison, <6 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison>
+; CHECK-NEXT: [[TMP14:%.*]] = shufflevector <6 x i64> [[TMP12]], <6 x i64> [[TMP13]], <6 x i32> <i32 0, i32 1, i32 6, i32 7, i32 8, i32 9>
+; CHECK-NEXT: store <6 x i64> [[TMP14]], ptr [[TMP0]], align 8
+; CHECK-NEXT: [[ARRAYIDX_91:%.*]] = getelementptr i8, ptr [[TMP0]], i64 96
+; CHECK-NEXT: [[ARRAYIDX_10:%.*]] = getelementptr i8, ptr [[TMP0]], i64 104
+; CHECK-NEXT: [[TMP15:%.*]] = extractelement <4 x i64> [[TMP11]], i64 0
+; CHECK-NEXT: [[TMP16:%.*]] = load <4 x i64>, ptr [[ARRAYIDX_91]], align 8
+; CHECK-NEXT: [[TMP17:%.*]] = load i64, ptr [[ARRAYIDX_10]], align 8
+; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <2 x i64> [[TMP5]], <2 x i64> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <4 x i64> [[TMP11]], <4 x i64> [[TMP18]], <2 x i32> <i32 3, i32 5>
+; CHECK-NEXT: [[TMP20:%.*]] = shufflevector <2 x i64> [[TMP19]], <2 x i64> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+; CHECK-NEXT: [[TMP21:%.*]] = shufflevector <4 x i64> [[TMP11]], <4 x i64> [[TMP20]], <4 x i32> <i32 1, i32 2, i32 4, i32 5>
+; CHECK-NEXT: [[TMP22:%.*]] = shufflevector <4 x i64> [[TMP21]], <4 x i64> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
+; CHECK-NEXT: [[TMP23:%.*]] = shufflevector <4 x i64> [[TMP16]], <4 x i64> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
+; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <8 x i64> [[TMP22]], <8 x i64> [[TMP23]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
+; CHECK-NEXT: [[TMP25:%.*]] = xor <8 x i64> [[TMP24]], <i64 0, i64 0, i64 0, i64 0, i64 1, i64 1, i64 1, i64 1>
+; CHECK-NEXT: [[TMP26:%.*]] = add <8 x i64> [[TMP25]], <i64 0, i64 0, i64 0, i64 0, i64 1, i64 1, i64 1, i64 1>
+; CHECK-NEXT: [[TMP27:%.*]] = extractelement <8 x i64> [[TMP26]], i64 4
+; CHECK-NEXT: store i64 [[TMP27]], ptr [[TMP0]], align 8
+; CHECK-NEXT: [[TMP28:%.*]] = extractelement <8 x i64> [[TMP26]], i64 5
+; CHECK-NEXT: store i64 [[TMP28]], ptr [[TMP0]], align 8
+; CHECK-NEXT: [[TMP29:%.*]] = extractelement <8 x i64> [[TMP26]], i64 6
+; CHECK-NEXT: store i64 [[TMP29]], ptr [[TMP0]], align 8
+; CHECK-NEXT: [[TMP30:%.*]] = extractelement <8 x i64> [[TMP26]], i64 7
+; CHECK-NEXT: store i64 [[TMP30]], ptr [[A]], align 8
+; CHECK-NEXT: [[TMP31:%.*]] = call i64 @llvm.vector.reduce.add.v8i64(<8 x i64> [[TMP26]])
+; CHECK-NEXT: [[OP_RDX:%.*]] = add i64 [[TMP31]], [[TMP15]]
+; CHECK-NEXT: [[OP_RDX1:%.*]] = add i64 [[OP_RDX]], [[TMP17]]
+; CHECK-NEXT: ret i64 [[OP_RDX1]]
+;
+entry:
+ %0 = load ptr, ptr %a, align 8
+ %arrayidx = getelementptr i8, ptr %0, i64 24
+ %1 = load i64, ptr %arrayidx, align 8
+ %xor = xor i64 %1, %d
+ %add1 = or i64 %xor, 1
+ store i64 %add1, ptr %0, align 8
+ %arrayidx.1 = getelementptr i8, ptr %0, i64 32
+ %2 = load i64, ptr %arrayidx.1, align 8
+ %add.1 = or i64 %d, 1
+ %xor.1 = xor i64 %2, %add.1
+ %add1.1 = or i64 %xor.1, 1
+ %arrayidx3.1 = getelementptr i8, ptr %0, i64 8
+ store i64 %add1.1, ptr %arrayidx3.1, align 8
+ %arrayidx.2 = getelementptr i8, ptr %0, i64 40
+ %3 = load i64, ptr %arrayidx.2, align 8
+ %xor.2 = xor i64 %3, %d
+ %add1.2 = add i64 %xor.2, 1
+ %arrayidx3.2 = getelementptr i8, ptr %0, i64 16
+ store i64 %add1.2, ptr %arrayidx3.2, align 8
+ %arrayidx.3 = getelementptr i8, ptr %0, i64 48
+ %4 = load i64, ptr %arrayidx.3, align 8
+ %add.3 = or i64 %d, 1
+ %xor.3 = xor i64 %4, %add.3
+ %add1.3 = add i64 %xor.3, 1
+ store i64 %add1.3, ptr %arrayidx, align 8
+ %arrayidx.4 = getelementptr i8, ptr %0, i64 56
+ %5 = load i64, ptr %arrayidx.4, align 8
+ %add.4 = or i64 %d, 1
+ %xor.4 = xor i64 %5, %add.4
+ %add1.4 = add i64 %xor.4, 1
+ store i64 %add1.4, ptr %arrayidx.1, align 8
+ %arrayidx.5 = getelementptr i8, ptr %0, i64 64
+ %6 = load i64, ptr %arrayidx.5, align 8
+ %xor.5 = xor i64 %6, 1
+ %add1.5 = add i64 %xor.5, 1
+ store i64 %add1.5, ptr %arrayidx.2, align 8
+ %arrayidx.91 = getelementptr i8, ptr %0, i64 96
+ %7 = load i64, ptr %arrayidx.91, align 8
+ %xor.9 = xor i64 %7, 1
+ %add1.9 = add i64 %xor.9, 1
+ store i64 %add1.9, ptr %0, align 8
+ %arrayidx.10 = getelementptr i8, ptr %0, i64 104
+ %8 = load i64, ptr %arrayidx.10, align 8
+ %xor.10 = xor i64 %8, 1
+ %add1.10 = add i64 %xor.10, 1
+ store i64 %add1.10, ptr %0, align 8
+ %arrayidx.11 = getelementptr i8, ptr %0, i64 112
+ %9 = load i64, ptr %arrayidx.11, align 8
+ %xor.11 = xor i64 %9, 1
+ %add1.11 = add i64 %xor.11, 1
+ store i64 %add1.11, ptr %0, align 8
+ %arrayidx.12 = getelementptr i8, ptr %0, i64 120
+ %10 = load i64, ptr %arrayidx.12, align 8
+ %xor.12 = xor i64 %10, 1
+ %add1.12 = add i64 %xor.12, 1
+ store i64 %add1.12, ptr %a, align 8
+ %add12.2 = add i64 %xor.1, %add1.2
+ %add12.3 = add i64 %add12.2, %add1.3
+ %add12.4 = add i64 %add12.3, %add1.4
+ %add12.5 = add i64 %add12.4, %add1.5
+ %add12.9 = add i64 %add12.5, %add1.9
+ %add12.10 = add i64 %add12.9, %add1.10
+ %add12.11 = add i64 %add12.10, %add1.11
+ %add12.12 = add i64 %add12.11, %add1.12
+ %add12.13 = add i64 %add12.12, %8
+ ret i64 %add12.13
+}
More information about the llvm-commits
mailing list