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

Alexey Bataev via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 5 09:50:52 PDT 2026


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

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


>From 8f6e352e5660af39cbd520215ef07af9db3c4e3a Mon Sep 17 00:00:00 2001
From: Alexey Bataev <a.bataev at outlook.com>
Date: Wed, 5 Aug 2026 09:50:36 -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    |  8 +++--
 .../fmuladd-absorbed-copyable-sched-deps.ll   | 32 +++++++++++++++++++
 2 files changed, 38 insertions(+), 2 deletions(-)

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
+}



More information about the llvm-commits mailing list