[llvm] [SLP]Fix unscheduled-deps assert for operands of copyable user lanes (PR #214283)

via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 5 09:51:36 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Alexey Bataev (alexey-bataev)

<details>
<summary>Changes</summary>

When every copyable model of an edge is skipped because the user is
itself a copyable lane, the instruction's own schedule data still
carries the def-use dependency counted by calculateDependencies. Release
it instead of returning early just because copyable data was found.

Fixes https://github.com/llvm/llvm-project/pull/213369#issuecomment-5189475412


---
Full diff: https://github.com/llvm/llvm-project/pull/214283.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp (+6-2) 
- (modified) llvm/test/Transforms/SLPVectorizer/AArch64/fmuladd-absorbed-copyable-sched-deps.ll (+32) 


``````````diff
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 229a225c6d413..3c14f2a0b595b 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -4857,15 +4857,19 @@ class slpvectorizer::BoUpSLP {
           if (!ScheduleCopyableDataMap.empty()) {
             SmallVector<ScheduleCopyableData *> CopyableData =
                 getScheduleCopyableData(User, OpIdx, I);
+            bool ReleasedAsCopyable = false;
             for (ScheduleCopyableData *CD : CopyableData) {
               // Copyable elements modeled on a copyable user lane depend on
               // the user's copyable scheduling data, not on the user itself,
-              // and are released when that copyable data is scheduled.
+              // and are released when that copyable data is scheduled. The
+              // user's own schedule data still carries the def-use dependency
+              // in this case, so it must be released below.
               if (CD->getEdgeInfo().UserTE->isCopyableElement(User))
                 continue;
               DecrUnsched(CD, /*IsControl=*/false);
+              ReleasedAsCopyable = true;
             }
-            if (!CopyableData.empty())
+            if (ReleasedAsCopyable)
               return;
           }
           if (ScheduleData *OpSD = getScheduleData(I))
diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/fmuladd-absorbed-copyable-sched-deps.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/fmuladd-absorbed-copyable-sched-deps.ll
index 128c25960d51a..217cc908065af 100644
--- a/llvm/test/Transforms/SLPVectorizer/AArch64/fmuladd-absorbed-copyable-sched-deps.ll
+++ b/llvm/test/Transforms/SLPVectorizer/AArch64/fmuladd-absorbed-copyable-sched-deps.ll
@@ -43,3 +43,35 @@ entry:
 declare double @llvm.fmuladd.f64(double, double, double) #0
 
 attributes #0 = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
+
+; The operand of the absorbed copyable fmul is itself a copyable lane of the
+; child node; the def-use dependency of that operand on the absorbed fmul must
+; be released when the fmul is scheduled.
+define void @absorbed_fmul_copyable_operand() {
+; CHECK-LABEL: define void @absorbed_fmul_copyable_operand() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, ptr poison, align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = fmul <4 x float> [[TMP0]], <float 1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT:    [[TMP2:%.*]] = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> [[TMP1]], <4 x float> zeroinitializer, <4 x float> <float -0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00>)
+; CHECK-NEXT:    store <4 x float> [[TMP2]], ptr poison, align 4
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = load float, ptr poison, align 4
+  %mul60 = fmul float %0, 0.000000e+00
+  store float %mul60, ptr poison, align 4
+  %arrayidx65 = getelementptr i8, ptr poison, i64 4
+  %1 = load float, ptr %arrayidx65, align 4
+  %neg = fmul float %1, 0.000000e+00
+  %2 = call float @llvm.fmuladd.f32(float %neg, float 0.000000e+00, float 0.000000e+00)
+  store float %2, ptr %arrayidx65, align 4
+  %arrayidx65.1 = getelementptr i8, ptr poison, i64 8
+  %3 = load float, ptr %arrayidx65.1, align 4
+  %4 = call float @llvm.fmuladd.f32(float %3, float 0.000000e+00, float 0.000000e+00)
+  store float %4, ptr %arrayidx65.1, align 4
+  %arrayidx65.2 = getelementptr i8, ptr poison, i64 12
+  %5 = load float, ptr %arrayidx65.2, align 4
+  %6 = call float @llvm.fmuladd.f32(float %5, float 0.000000e+00, float 0.000000e+00)
+  store float %6, ptr %arrayidx65.2, align 4
+  ret void
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/214283


More information about the llvm-commits mailing list