[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