[llvm] [SLP]Fix crash in getReorderingData on all-poison reuse-mask slice (PR #194392)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 27 07:54:12 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-vectorizers
Author: Alexey Bataev (alexey-bataev)
<details>
<summary>Changes</summary>
When the reuse-shuffle mask is iterated in Sz-sized parts and a part is
entirely PoisonMaskElem, `Val` stays at PoisonMaskElem (-1) and the
subsequent `UsedVals.test(Val)` trips the SmallBitVector OOB assertion.
Bail out of reordering in that case.
Fixes #<!-- -->194315
---
Full diff: https://github.com/llvm/llvm-project/pull/194392.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp (+3-3)
- (added) llvm/test/Transforms/SLPVectorizer/X86/identity-reuses-with-poisons.ll (+114)
``````````diff
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 13cab4fd1e5c8..6a0ff011eb96d 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -8224,8 +8224,8 @@ BoUpSLP::getReorderingData(const TreeEntry &TE, bool TopToBottom,
++UndefCnt;
return Idx != PoisonMaskElem && Idx != Val;
}) ||
- Val >= static_cast<int>(NumParts) || UsedVals.test(Val) ||
- UndefCnt > Sz / 2)
+ Val >= static_cast<int>(NumParts) || Val == PoisonMaskElem ||
+ UsedVals.test(Val) || UndefCnt > Sz / 2)
return std::nullopt;
UsedVals.set(Val);
for (unsigned K = 0; K < NumParts; ++K) {
@@ -11281,7 +11281,7 @@ static bool tryToFindDuplicates(SmallVectorImpl<Value *> &VL,
if (isConstant(V))
UniquesDemandedElts.clearBit(Idx);
InstructionCost UniquesCost =
- (!BuildGatherOnly || R.hasSameNode(S, UniqueValues))
+ CanSkipBVCost
? InstructionCost(TTI::TCC_Free)
: ::getScalarizationOverhead(TTI, ScalarTy, UniquesVecTy,
UniquesDemandedElts, /*Insert=*/true,
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/identity-reuses-with-poisons.ll b/llvm/test/Transforms/SLPVectorizer/X86/identity-reuses-with-poisons.ll
new file mode 100644
index 0000000000000..aa32e4e3f1f8d
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/identity-reuses-with-poisons.ll
@@ -0,0 +1,114 @@
+; 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
+
+define void @test(ptr %a, i32 %0, i1 %tobool13.not) {
+; CHECK-LABEL: define void @test(
+; CHECK-SAME: ptr [[A:%.*]], i32 [[TMP0:%.*]], i1 [[TOBOOL13_NOT:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: br label %[[AG:.*]]
+; CHECK: [[AJ:.*]]:
+; CHECK-NEXT: [[AA_0:%.*]] = phi i32 [ [[AA_3:%.*]], %[[CLEANUP_CONT:.*]] ], [ 0, %[[IF_THEN10:.*]] ]
+; CHECK-NEXT: [[AE_0:%.*]] = phi i32 [ [[AE_3:%.*]], %[[CLEANUP_CONT]] ], [ [[AE_1:%.*]], %[[IF_THEN10]] ]
+; CHECK-NEXT: [[AS_0:%.*]] = phi i32 [ poison, %[[CLEANUP_CONT]] ], [ [[TMP1:%.*]], %[[IF_THEN10]] ]
+; CHECK-NEXT: [[AB_0:%.*]] = phi i32 [ poison, %[[CLEANUP_CONT]] ], [ [[AB_2:%.*]], %[[IF_THEN10]] ]
+; CHECK-NEXT: [[L_0:%.*]] = phi i32 [ poison, %[[CLEANUP_CONT]] ], [ [[L_2:%.*]], %[[IF_THEN10]] ]
+; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[AA_3]], 1
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[AB_0]], 1
+; CHECK-NEXT: br label %[[IF_END4:.*]]
+; CHECK: [[AO:.*]]:
+; CHECK-NEXT: [[NOT18:%.*]] = xor i32 [[AE_3]], 1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[AN_3:%.*]], [[AM_3:%.*]]
+; CHECK-NEXT: br label %[[IF_END4]]
+; CHECK: [[IF_END4]]:
+; CHECK-NEXT: [[AA_1:%.*]] = phi i32 [ [[AA_0]], %[[AJ]] ], [ [[AA_3]], %[[AO]] ]
+; CHECK-NEXT: [[AE_1]] = phi i32 [ [[AE_0]], %[[AJ]] ], [ [[AND]], %[[AO]] ]
+; CHECK-NEXT: [[AH_2:%.*]] = phi i32 [ [[AS_0]], %[[AJ]] ], [ [[TMP0]], %[[AO]] ]
+; CHECK-NEXT: [[AM_1:%.*]] = phi i32 [ [[NOT]], %[[AJ]] ], [ 0, %[[AO]] ]
+; CHECK-NEXT: [[AN_1:%.*]] = phi i32 [ [[XOR]], %[[AJ]] ], [ 0, %[[AO]] ]
+; CHECK-NEXT: [[AS_2:%.*]] = phi i32 [ [[AS_0]], %[[AJ]] ], [ 0, %[[AO]] ]
+; CHECK-NEXT: [[AB_2]] = phi i32 [ [[AB_0]], %[[AJ]] ], [ [[AH_43:%.*]], %[[AO]] ]
+; CHECK-NEXT: [[L_2]] = phi i32 [ [[L_0]], %[[AJ]] ], [ [[NOT18]], %[[AO]] ]
+; CHECK-NEXT: [[TOBOOL5_NOT:%.*]] = icmp eq i32 [[AH_2]], 0
+; CHECK-NEXT: br i1 [[TOBOOL5_NOT]], label %[[IF_END7:.*]], label %[[AG]]
+; CHECK: [[IF_END7]]:
+; CHECK-NEXT: [[TOBOOL9_NOT:%.*]] = icmp eq i32 [[L_2]], 0
+; CHECK-NEXT: br i1 [[TOBOOL9_NOT]], label %[[AG]], label %[[IF_THEN10]]
+; CHECK: [[IF_THEN10]]:
+; CHECK-NEXT: [[TMP1]] = load i32, ptr [[A]], align 4
+; CHECK-NEXT: [[NOT11:%.*]] = xor i32 [[TMP0]], 1
+; CHECK-NEXT: br i1 [[TOBOOL13_NOT]], label %[[AG]], label %[[AJ]]
+; CHECK: [[AG]]:
+; CHECK-NEXT: [[AA_3]] = phi i32 [ 0, %[[ENTRY]] ], [ [[AA_3]], %[[IF_END4]] ], [ [[AA_1]], %[[IF_END7]] ], [ [[NOT11]], %[[IF_THEN10]] ], [ [[AA_3]], %[[AG]] ]
+; CHECK-NEXT: [[AE_3]] = phi i32 [ 0, %[[ENTRY]] ], [ [[AE_3]], %[[IF_END4]] ], [ [[AE_3]], %[[IF_END7]] ], [ [[AE_1]], %[[IF_THEN10]] ], [ 0, %[[AG]] ]
+; CHECK-NEXT: [[AH_43]] = phi i32 [ 0, %[[ENTRY]] ], [ 1, %[[IF_END4]] ], [ 0, %[[IF_END7]] ], [ 0, %[[IF_THEN10]] ], [ 0, %[[AG]] ]
+; CHECK-NEXT: [[AM_3]] = phi i32 [ 0, %[[ENTRY]] ], [ 0, %[[IF_END4]] ], [ [[AM_1]], %[[IF_END7]] ], [ 0, %[[IF_THEN10]] ], [ 0, %[[AG]] ]
+; CHECK-NEXT: [[AN_3]] = phi i32 [ 0, %[[ENTRY]] ], [ 0, %[[IF_END4]] ], [ [[AN_1]], %[[IF_END7]] ], [ 0, %[[IF_THEN10]] ], [ 0, %[[AG]] ]
+; CHECK-NEXT: [[AS_4:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[AS_2]], %[[IF_END4]] ], [ 0, %[[IF_END7]] ], [ 0, %[[IF_THEN10]] ], [ 0, %[[AG]] ]
+; CHECK-NEXT: switch i32 [[TMP0]], label %[[CLEANUP_CONT]] [
+; CHECK-NEXT: i32 5, label %[[AG]]
+; CHECK-NEXT: i32 4, label %[[AO]]
+; CHECK-NEXT: ]
+; CHECK: [[CLEANUP_CONT]]:
+; CHECK-NEXT: [[TOBOOL29_NOT:%.*]] = icmp eq i32 [[AS_4]], 0
+; CHECK-NEXT: br i1 [[TOBOOL29_NOT]], label %[[COMMON_RET:.*]], label %[[AJ]]
+; CHECK: [[COMMON_RET]]:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %ag
+
+aj:
+ %aa.0 = phi i32 [ %aa.3, %cleanup.cont ], [ 0, %if.then10 ]
+ %ae.0 = phi i32 [ %ae.3, %cleanup.cont ], [ %ae.1, %if.then10 ]
+ %as.0 = phi i32 [ poison, %cleanup.cont ], [ %1, %if.then10 ]
+ %ab.0 = phi i32 [ poison, %cleanup.cont ], [ %ab.2, %if.then10 ]
+ %l.0 = phi i32 [ poison, %cleanup.cont ], [ %l.2, %if.then10 ]
+ %not = xor i32 %aa.3, 1
+ %xor = xor i32 %ab.0, 1
+ br label %if.end4
+
+ao:
+ %not18 = xor i32 %ae.3, 1
+ %and = and i32 %an.3, %am.3
+ br label %if.end4
+
+if.end4:
+ %aa.1 = phi i32 [ %aa.0, %aj ], [ %aa.3, %ao ]
+ %ae.1 = phi i32 [ %ae.0, %aj ], [ %and, %ao ]
+ %ah.2 = phi i32 [ %as.0, %aj ], [ %0, %ao ]
+ %am.1 = phi i32 [ %not, %aj ], [ 0, %ao ]
+ %an.1 = phi i32 [ %xor, %aj ], [ 0, %ao ]
+ %as.2 = phi i32 [ %as.0, %aj ], [ 0, %ao ]
+ %ab.2 = phi i32 [ %ab.0, %aj ], [ %ah.43, %ao ]
+ %l.2 = phi i32 [ %l.0, %aj ], [ %not18, %ao ]
+ %tobool5.not = icmp eq i32 %ah.2, 0
+ br i1 %tobool5.not, label %if.end7, label %ag
+
+if.end7:
+ %tobool9.not = icmp eq i32 %l.2, 0
+ br i1 %tobool9.not, label %ag, label %if.then10
+
+if.then10:
+ %1 = load i32, ptr %a, align 4
+ %not11 = xor i32 %0, 1
+ br i1 %tobool13.not, label %ag, label %aj
+
+ag:
+ %aa.3 = phi i32 [ 0, %entry ], [ %aa.3, %if.end4 ], [ %aa.1, %if.end7 ], [ %not11, %if.then10 ], [ %aa.3, %ag ]
+ %ae.3 = phi i32 [ 0, %entry ], [ %ae.3, %if.end4 ], [ %ae.3, %if.end7 ], [ %ae.1, %if.then10 ], [ 0, %ag ]
+ %ah.43 = phi i32 [ 0, %entry ], [ 1, %if.end4 ], [ 0, %if.end7 ], [ 0, %if.then10 ], [ 0, %ag ]
+ %am.3 = phi i32 [ 0, %entry ], [ 0, %if.end4 ], [ %am.1, %if.end7 ], [ 0, %if.then10 ], [ 0, %ag ]
+ %an.3 = phi i32 [ 0, %entry ], [ 0, %if.end4 ], [ %an.1, %if.end7 ], [ 0, %if.then10 ], [ 0, %ag ]
+ %as.4 = phi i32 [ 0, %entry ], [ %as.2, %if.end4 ], [ 0, %if.end7 ], [ 0, %if.then10 ], [ 0, %ag ]
+ switch i32 %0, label %cleanup.cont [
+ i32 5, label %ag
+ i32 4, label %ao
+ ]
+
+cleanup.cont:
+ %tobool29.not = icmp eq i32 %as.4, 0
+ br i1 %tobool29.not, label %common.ret, label %aj
+
+common.ret:
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/194392
More information about the llvm-commits
mailing list