[llvm] [SLP] Fix scheduling crash for reordered insertvalue buildvector nodes (PR #204941)

Alexey Bataev via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 20 11:54:11 PDT 2026


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

Insertvalue nodes keep scalars in program order but reorder operands, like
stores. Remap the operand lane via ReorderIndices for InsertValueInst (not
just StoreInst) in scheduling and the copyable helpers, fixing the
"Operand not found" assertion.

Fixes https://github.com/llvm/llvm-project/pull/200274#issuecomment-4753792761


>From 089dd631ba1156256d399696728a1ab14dc1b658 Mon Sep 17 00:00:00 2001
From: Alexey Bataev <a.bataev at outlook.com>
Date: Sat, 20 Jun 2026 11:53:59 -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    | 11 ++--
 .../X86/insertvalue-reordered-operands.ll     | 62 +++++++++++++++++++
 2 files changed, 68 insertions(+), 5 deletions(-)
 create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/insertvalue-reordered-operands.ll

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 9b7d154598c40..52566c094f6a6 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -5792,7 +5792,8 @@ class slpvectorizer::BoUpSLP {
                  "User is not in the tree entry");
           int Lane = std::distance(P.first->Scalars.begin(), It);
           assert(Lane >= 0 && "Lane is not found");
-          if (isa<StoreInst>(User) && !P.first->ReorderIndices.empty())
+          if (isa<StoreInst, InsertValueInst>(User) &&
+              !P.first->ReorderIndices.empty())
             Lane = P.first->ReorderIndices[Lane];
           assert(Lane < static_cast<int>(P.first->Scalars.size()) &&
                  "Couldn't find extract lane");
@@ -5875,7 +5876,7 @@ class slpvectorizer::BoUpSLP {
         do {
           int Lane = std::distance(Op.begin(), It);
           assert(Lane >= 0 && "Lane not set");
-          if (isa<StoreInst>(EI.UserTE->Scalars[Lane]) &&
+          if (isa<StoreInst, InsertValueInst>(EI.UserTE->Scalars[Lane]) &&
               !EI.UserTE->ReorderIndices.empty())
             Lane = EI.UserTE->ReorderIndices[Lane];
           assert(Lane < static_cast<int>(EI.UserTE->Scalars.size()) &&
@@ -6078,7 +6079,7 @@ class slpvectorizer::BoUpSLP {
               int Lane =
                   std::distance(Bundle->getTreeEntry()->Scalars.begin(), It);
               assert(Lane >= 0 && "Lane not set");
-              if (isa<StoreInst>(In) &&
+              if (isa<StoreInst, InsertValueInst>(In) &&
                   !Bundle->getTreeEntry()->ReorderIndices.empty())
                 Lane = Bundle->getTreeEntry()->ReorderIndices[Lane];
               assert(Lane < static_cast<int>(
@@ -25911,7 +25912,7 @@ BoUpSLP::BlockScheduling::tryScheduleBundle(ArrayRef<Value *> VL, BoUpSLP *SLP,
           do {
             int Lane = std::distance(Op.begin(), It);
             assert(Lane >= 0 && "Lane not set");
-            if (isa<StoreInst>(EI.UserTE->Scalars[Lane]) &&
+            if (isa<StoreInst, InsertValueInst>(EI.UserTE->Scalars[Lane]) &&
                 !EI.UserTE->ReorderIndices.empty())
               Lane = EI.UserTE->ReorderIndices[Lane];
             assert(Lane < static_cast<int>(EI.UserTE->Scalars.size()) &&
@@ -26118,7 +26119,7 @@ void BoUpSLP::BlockScheduling::calculateDependencies(
         do {
           int Lane = std::distance(Op.begin(), It);
           assert(Lane >= 0 && "Lane not set");
-          if (isa<StoreInst>(EI.UserTE->Scalars[Lane]) &&
+          if (isa<StoreInst, InsertValueInst>(EI.UserTE->Scalars[Lane]) &&
               !EI.UserTE->ReorderIndices.empty())
             Lane = EI.UserTE->ReorderIndices[Lane];
           assert(Lane < static_cast<int>(EI.UserTE->Scalars.size()) &&
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/insertvalue-reordered-operands.ll b/llvm/test/Transforms/SLPVectorizer/X86/insertvalue-reordered-operands.ll
new file mode 100644
index 0000000000000..b74d11c18b794
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/insertvalue-reordered-operands.ll
@@ -0,0 +1,62 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -mtriple=x86_64-unknown-linux-gnu -passes=slp-vectorizer < %s | FileCheck %s
+
+define { i64, i64 } @test(ptr %arg1) {
+; CHECK-LABEL: define { i64, i64 } @test(
+; CHECK-SAME: ptr [[ARG1:%.*]]) {
+; CHECK-NEXT:  [[BB:.*:]]
+; CHECK-NEXT:    [[VEC2STRUCT_SLOT:%.*]] = alloca { i64, i64 }, align 16
+; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i32>, ptr [[ARG1]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = sitofp <2 x i32> [[TMP0]] to <2 x float>
+; CHECK-NEXT:    [[TMP2:%.*]] = fpext <2 x float> [[TMP1]] to <2 x double>
+; CHECK-NEXT:    [[TMP3:%.*]] = bitcast <2 x double> [[TMP2]] to <2 x i64>
+; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <2 x i64> [[TMP3]], <2 x i64> poison, <2 x i32> <i32 1, i32 0>
+; CHECK-NEXT:    store <2 x i64> [[TMP5]], ptr [[VEC2STRUCT_SLOT]], align 16
+; CHECK-NEXT:    [[VEC2STRUCT:%.*]] = load { i64, i64 }, ptr [[VEC2STRUCT_SLOT]], align 16
+; CHECK-NEXT:    ret { i64, i64 } [[VEC2STRUCT]]
+;
+bb:
+  %getelementptr = getelementptr i8, ptr %arg1, i64 4
+  %load = load i32, ptr %arg1, align 4
+  %sitofp = sitofp i32 %load to float
+  %load4 = load i32, ptr %getelementptr, align 4
+  %sitofp5 = sitofp i32 %load4 to float
+  %fpext = fpext float %sitofp5 to double
+  %bitcast.i = bitcast double %fpext to i64
+  %insertvalue = insertvalue { i64, i64 } poison, i64 %bitcast.i, 0
+  %fpext9 = fpext float %sitofp to double
+  %bitcast.i12 = bitcast double %fpext9 to i64
+  %insertvalue14 = insertvalue { i64, i64 } %insertvalue, i64 %bitcast.i12, 1
+  ret { i64, i64 } %insertvalue14
+}
+
+define { i64, i64 } @testi1(ptr %arg1) {
+; CHECK-LABEL: define { i64, i64 } @testi1(
+; CHECK-SAME: ptr [[ARG1:%.*]]) {
+; CHECK-NEXT:  [[BB:.*:]]
+; CHECK-NEXT:    [[VEC2STRUCT_SLOT:%.*]] = alloca { i64, i64 }, align 16
+; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i32>, ptr [[ARG1]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = sitofp <2 x i32> [[TMP0]] to <2 x float>
+; CHECK-NEXT:    [[TMP2:%.*]] = fpext <2 x float> [[TMP1]] to <2 x double>
+; CHECK-NEXT:    [[TMP3:%.*]] = bitcast <2 x double> [[TMP2]] to <2 x i64>
+; CHECK-NEXT:    [[TMP4:%.*]] = and <2 x i64> [[TMP3]], <i64 -1, i64 1>
+; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <2 x i64> [[TMP4]], <2 x i64> poison, <2 x i32> <i32 1, i32 0>
+; CHECK-NEXT:    store <2 x i64> [[TMP5]], ptr [[VEC2STRUCT_SLOT]], align 16
+; CHECK-NEXT:    [[VEC2STRUCT:%.*]] = load { i64, i64 }, ptr [[VEC2STRUCT_SLOT]], align 16
+; CHECK-NEXT:    ret { i64, i64 } [[VEC2STRUCT]]
+;
+bb:
+  %gep = getelementptr i8, ptr %arg1, i64 4
+  %load = load i32, ptr %arg1, align 4
+  %sitofp = sitofp i32 %load to float
+  %load4 = load i32, ptr %gep, align 4
+  %sitofp5 = sitofp i32 %load4 to float
+  %fpext = fpext float %sitofp5 to double
+  %bc = bitcast double %fpext to i64
+  %fpext9 = fpext float %sitofp to double
+  %bc9 = bitcast double %fpext9 to i64
+  %and = and i64 %bc, 1
+  %iv0 = insertvalue { i64, i64 } poison, i64 %and, 0
+  %iv1 = insertvalue { i64, i64 } %iv0, i64 %bc9, 1
+  ret { i64, i64 } %iv1
+}



More information about the llvm-commits mailing list