[llvm] 3deeb01 - [SLP]Fix dep accounting when cancelling a bundle with repeated copyable users

via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 13 04:42:50 PDT 2026


Author: Alexey Bataev
Date: 2026-09-13T07:42:46-04:00
New Revision: 3deeb018ed1d1c61ad9e1798161128e0202e7920

URL: https://github.com/llvm/llvm-project/commit/3deeb018ed1d1c61ad9e1798161128e0202e7920
DIFF: https://github.com/llvm/llvm-project/commit/3deeb018ed1d1c61ad9e1798161128e0202e7920.diff

LOG: [SLP]Fix dep accounting when cancelling a bundle with repeated copyable users

Skip duplicate users instead of stopping at the first one when walking
the operand lanes; an early stop misses a trailing self-use lane, the
displaced parent-edge copyable data is never restored, and scheduling
asserts.

Fixes #223225

Reviewers: 

Pull Request: https://github.com/llvm/llvm-project/pull/223236

Added: 
    llvm/test/Transforms/SLPVectorizer/X86/cancelled-copyable-self-use-deps-2.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 d7c96346feca0..4feedf5febff3 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -26184,7 +26184,7 @@ BoUpSLP::BlockScheduling::tryScheduleBundle(ArrayRef<Value *> VL, BoUpSLP *SLP,
             auto *In = cast<Instruction>(EI.UserTE->Scalars[Lane]);
             if (!Visited.insert(In).second) {
               It = find(make_range(std::next(It), Op.end()), I);
-              break;
+              continue;
             }
             HadSelfUse |= In == I;
             ScheduleCopyableDataMapByInstUser

diff  --git a/llvm/test/Transforms/SLPVectorizer/X86/cancelled-copyable-self-use-deps-2.ll b/llvm/test/Transforms/SLPVectorizer/X86/cancelled-copyable-self-use-deps-2.ll
new file mode 100644
index 0000000000000..994639ee9e422
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/cancelled-copyable-self-use-deps-2.ll
@@ -0,0 +1,180 @@
+; 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-pc-linux-gnu | FileCheck %s
+
+define i32 @test(ptr %0, ptr %1, ptr %2, i8 %3, i32 %4, i32 %5) {
+; CHECK-LABEL: define i32 @test(
+; CHECK-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]], i8 [[TMP3:%.*]], i32 [[TMP4:%.*]], i32 [[TMP5:%.*]]) {
+; CHECK-NEXT:    [[TMP7:%.*]] = load i8, ptr [[TMP0]], align 1
+; CHECK-NEXT:    [[TMP8:%.*]] = zext i8 [[TMP7]] to i32
+; CHECK-NEXT:    [[TMP9:%.*]] = shl i32 [[TMP8]], 1
+; CHECK-NEXT:    [[TMP10:%.*]] = zext i8 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP11:%.*]] = shl i32 [[TMP10]], 1
+; CHECK-NEXT:    [[TMP12:%.*]] = zext i8 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP13:%.*]] = shl i32 [[TMP12]], 1
+; CHECK-NEXT:    [[TMP14:%.*]] = add i32 [[TMP4]], [[TMP9]]
+; CHECK-NEXT:    [[TMP15:%.*]] = add i32 [[TMP14]], 1
+; CHECK-NEXT:    [[TMP16:%.*]] = lshr i32 [[TMP15]], 1
+; CHECK-NEXT:    [[TMP17:%.*]] = trunc i32 [[TMP16]] to i8
+; CHECK-NEXT:    store i8 [[TMP17]], ptr [[TMP0]], align 1
+; CHECK-NEXT:    [[TMP18:%.*]] = add i32 [[TMP11]], [[TMP4]]
+; CHECK-NEXT:    [[TMP19:%.*]] = add i32 [[TMP18]], 1
+; CHECK-NEXT:    [[TMP20:%.*]] = lshr i32 [[TMP19]], 1
+; CHECK-NEXT:    [[TMP21:%.*]] = trunc i32 [[TMP20]] to i8
+; CHECK-NEXT:    store i8 [[TMP21]], ptr [[TMP1]], align 1
+; CHECK-NEXT:    [[TMP22:%.*]] = add i32 [[TMP13]], [[TMP4]]
+; CHECK-NEXT:    [[TMP23:%.*]] = add i32 [[TMP22]], 1
+; CHECK-NEXT:    [[TMP24:%.*]] = lshr i32 [[TMP23]], 1
+; CHECK-NEXT:    [[TMP25:%.*]] = trunc i32 [[TMP24]] to i8
+; CHECK-NEXT:    store i8 [[TMP25]], ptr [[TMP0]], align 1
+; CHECK-NEXT:    [[TMP26:%.*]] = zext i8 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP27:%.*]] = shl i32 [[TMP26]], 1
+; CHECK-NEXT:    [[TMP28:%.*]] = add i32 [[TMP27]], [[TMP4]]
+; CHECK-NEXT:    [[TMP29:%.*]] = add i32 [[TMP28]], 1
+; CHECK-NEXT:    [[TMP30:%.*]] = lshr i32 [[TMP29]], 1
+; CHECK-NEXT:    store i32 [[TMP30]], ptr [[TMP0]], align 1
+; CHECK-NEXT:    [[TMP31:%.*]] = zext i8 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP32:%.*]] = shl i32 [[TMP31]], 1
+; CHECK-NEXT:    [[TMP33:%.*]] = or i32 [[TMP32]], [[TMP4]]
+; CHECK-NEXT:    [[TMP34:%.*]] = or i32 [[TMP33]], [[TMP5]]
+; CHECK-NEXT:    [[TMP35:%.*]] = lshr i32 [[TMP34]], 1
+; CHECK-NEXT:    [[TMP36:%.*]] = trunc i32 [[TMP35]] to i8
+; CHECK-NEXT:    store i8 [[TMP36]], ptr [[TMP1]], align 1
+; CHECK-NEXT:    [[TMP37:%.*]] = add i32 [[TMP27]], [[TMP4]]
+; CHECK-NEXT:    [[TMP38:%.*]] = add i32 [[TMP37]], 1
+; CHECK-NEXT:    [[TMP39:%.*]] = lshr i32 [[TMP38]], 1
+; CHECK-NEXT:    [[TMP40:%.*]] = trunc i32 [[TMP39]] to i8
+; CHECK-NEXT:    store i8 [[TMP40]], ptr [[TMP0]], align 1
+; CHECK-NEXT:    [[TMP41:%.*]] = or i32 [[TMP26]], 1
+; CHECK-NEXT:    [[TMP42:%.*]] = add i32 [[TMP41]], 1
+; CHECK-NEXT:    [[TMP43:%.*]] = lshr i32 [[TMP42]], 1
+; CHECK-NEXT:    [[TMP44:%.*]] = trunc i32 [[TMP43]] to i8
+; CHECK-NEXT:    store i8 [[TMP44]], ptr [[TMP1]], align 1
+; CHECK-NEXT:    [[TMP45:%.*]] = or i32 [[TMP4]], [[TMP8]]
+; CHECK-NEXT:    [[TMP46:%.*]] = or i32 [[TMP45]], [[TMP5]]
+; CHECK-NEXT:    [[TMP47:%.*]] = lshr i32 [[TMP46]], 1
+; CHECK-NEXT:    [[TMP48:%.*]] = trunc i32 [[TMP47]] to i8
+; CHECK-NEXT:    store i8 [[TMP48]], ptr [[TMP2]], align 1
+; CHECK-NEXT:    [[TMP49:%.*]] = add i32 [[TMP11]], [[TMP4]]
+; CHECK-NEXT:    [[TMP50:%.*]] = add i32 [[TMP49]], 1
+; CHECK-NEXT:    [[TMP51:%.*]] = lshr i32 [[TMP50]], 1
+; CHECK-NEXT:    [[TMP52:%.*]] = trunc i32 [[TMP51]] to i8
+; CHECK-NEXT:    store i8 [[TMP52]], ptr [[TMP0]], align 1
+; CHECK-NEXT:    [[TMP53:%.*]] = add i32 [[TMP8]], 1
+; CHECK-NEXT:    [[TMP54:%.*]] = lshr i32 [[TMP53]], 1
+; CHECK-NEXT:    [[TMP55:%.*]] = trunc i32 [[TMP54]] to i8
+; CHECK-NEXT:    store i8 [[TMP55]], ptr [[TMP1]], align 1
+; CHECK-NEXT:    [[TMP56:%.*]] = add i32 [[TMP8]], 1
+; CHECK-NEXT:    [[TMP57:%.*]] = or i32 [[TMP56]], [[TMP4]]
+; CHECK-NEXT:    [[TMP58:%.*]] = lshr i32 [[TMP57]], 1
+; CHECK-NEXT:    [[TMP59:%.*]] = trunc i32 [[TMP58]] to i8
+; CHECK-NEXT:    store i8 [[TMP59]], ptr [[TMP0]], align 1
+; CHECK-NEXT:    [[TMP60:%.*]] = add i32 [[TMP10]], 1
+; CHECK-NEXT:    [[TMP61:%.*]] = lshr i32 [[TMP60]], 1
+; CHECK-NEXT:    [[TMP62:%.*]] = trunc i32 [[TMP61]] to i8
+; CHECK-NEXT:    store i8 [[TMP62]], ptr [[TMP1]], align 1
+; CHECK-NEXT:    [[TMP63:%.*]] = zext i8 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP64:%.*]] = add i32 [[TMP63]], 1
+; CHECK-NEXT:    [[TMP65:%.*]] = lshr i32 [[TMP64]], 1
+; CHECK-NEXT:    [[TMP66:%.*]] = trunc i32 [[TMP65]] to i8
+; CHECK-NEXT:    store i8 [[TMP66]], ptr [[TMP0]], align 1
+; CHECK-NEXT:    [[TMP67:%.*]] = add i32 [[TMP13]], [[TMP4]]
+; CHECK-NEXT:    [[TMP68:%.*]] = add i32 [[TMP67]], 1
+; CHECK-NEXT:    [[TMP69:%.*]] = lshr i32 [[TMP68]], 1
+; CHECK-NEXT:    [[TMP70:%.*]] = trunc i32 [[TMP69]] to i8
+; CHECK-NEXT:    store i8 [[TMP70]], ptr [[TMP1]], align 1
+; CHECK-NEXT:    [[TMP71:%.*]] = add i32 [[TMP63]], 1
+; CHECK-NEXT:    [[TMP72:%.*]] = add i32 [[TMP71]], [[TMP4]]
+; CHECK-NEXT:    [[TMP73:%.*]] = lshr i32 [[TMP72]], 1
+; CHECK-NEXT:    [[TMP74:%.*]] = trunc i32 [[TMP73]] to i8
+; CHECK-NEXT:    store i8 [[TMP74]], ptr [[TMP0]], align 1
+; CHECK-NEXT:    [[TMP75:%.*]] = or i32 [[TMP4]], [[TMP63]]
+; CHECK-NEXT:    [[TMP76:%.*]] = lshr i32 [[TMP75]], 1
+; CHECK-NEXT:    ret i32 [[TMP76]]
+;
+  %7 = load i8, ptr %0, align 1
+  %8 = zext i8 %7 to i32
+  %9 = shl i32 %8, 1
+  %10 = zext i8 %3 to i32
+  %11 = shl i32 %10, 1
+  %12 = zext i8 %3 to i32
+  %13 = shl i32 %12, 1
+  %14 = add i32 %4, %9
+  %15 = add i32 %14, 1
+  %16 = lshr i32 %15, 1
+  %17 = trunc i32 %16 to i8
+  store i8 %17, ptr %0, align 1
+  %18 = add i32 %11, %4
+  %19 = add i32 %18, 1
+  %20 = lshr i32 %19, 1
+  %21 = trunc i32 %20 to i8
+  store i8 %21, ptr %1, align 1
+  %22 = add i32 %13, %4
+  %23 = add i32 %22, 1
+  %24 = lshr i32 %23, 1
+  %25 = trunc i32 %24 to i8
+  store i8 %25, ptr %0, align 1
+  %26 = zext i8 %3 to i32
+  %27 = shl i32 %26, 1
+  %28 = add i32 %27, %4
+  %29 = add i32 %28, 1
+  %30 = lshr i32 %29, 1
+  store i32 %30, ptr %0, align 1
+  %31 = zext i8 %3 to i32
+  %32 = shl i32 %31, 1
+  %33 = or i32 %32, %4
+  %34 = or i32 %33, %5
+  %35 = lshr i32 %34, 1
+  %36 = trunc i32 %35 to i8
+  store i8 %36, ptr %1, align 1
+  %37 = add i32 %27, %4
+  %38 = add i32 %37, 1
+  %39 = lshr i32 %38, 1
+  %40 = trunc i32 %39 to i8
+  store i8 %40, ptr %0, align 1
+  %41 = or i32 %26, 1
+  %42 = add i32 %41, 1
+  %43 = lshr i32 %42, 1
+  %44 = trunc i32 %43 to i8
+  store i8 %44, ptr %1, align 1
+  %45 = or i32 %4, %8
+  %46 = or i32 %45, %5
+  %47 = lshr i32 %46, 1
+  %48 = trunc i32 %47 to i8
+  store i8 %48, ptr %2, align 1
+  %49 = add i32 %11, %4
+  %50 = add i32 %49, 1
+  %51 = lshr i32 %50, 1
+  %52 = trunc i32 %51 to i8
+  store i8 %52, ptr %0, align 1
+  %53 = add i32 %8, 1
+  %54 = lshr i32 %53, 1
+  %55 = trunc i32 %54 to i8
+  store i8 %55, ptr %1, align 1
+  %56 = add i32 %8, 1
+  %57 = or i32 %56, %4
+  %58 = lshr i32 %57, 1
+  %59 = trunc i32 %58 to i8
+  store i8 %59, ptr %0, align 1
+  %60 = add i32 %10, 1
+  %61 = lshr i32 %60, 1
+  %62 = trunc i32 %61 to i8
+  store i8 %62, ptr %1, align 1
+  %63 = zext i8 %3 to i32
+  %64 = add i32 %63, 1
+  %65 = lshr i32 %64, 1
+  %66 = trunc i32 %65 to i8
+  store i8 %66, ptr %0, align 1
+  %67 = add i32 %13, %4
+  %68 = add i32 %67, 1
+  %69 = lshr i32 %68, 1
+  %70 = trunc i32 %69 to i8
+  store i8 %70, ptr %1, align 1
+  %71 = add i32 %63, 1
+  %72 = add i32 %71, %4
+  %73 = lshr i32 %72, 1
+  %74 = trunc i32 %73 to i8
+  store i8 %74, ptr %0, align 1
+  %75 = or i32 %4, %63
+  %76 = lshr i32 %75, 1
+  ret i32 %76
+}


        


More information about the llvm-commits mailing list