[llvm] [SLP] Fix reduction cost crash for reduced values replaced by extractelement (PR #204847)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 19 08:54:30 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>

A reduced value may be replaced by an extractelement while vectorizing a
previous subvector, so it is no longer a key in ReducedValsToOps.
Look through replaced values to the reduction operation among their users.

Fixes #<!-- -->204814


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


2 Files Affected:

- (modified) llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp (+15-2) 
- (added) llvm/test/Transforms/SLPVectorizer/X86/reduced-value-replace-extractelement-cost.ll (+61) 


``````````diff
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 68c11dc372ad7..9b7d154598c40 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -30551,6 +30551,19 @@ class HorizontalReduction {
     // If all of the reduced values are constant, the vector cost is 0, since
     // the reduction value can be calculated at the compile time.
     bool AllConsts = allConstant(ReducedVals);
+    // A reduced value may have been replaced by an extractelement while
+    // vectorizing a previous subvector of the reduction. Such tracked values
+    // are not present in ReducedValsToOps, so look through them to the
+    // reduction operation that uses the replaced value.
+    auto GetReductionOp = [&](Value *RdxVal) -> Instruction * {
+      auto It = ReducedValsToOps.find(RdxVal);
+      if (It != ReducedValsToOps.end())
+        return It->second.front();
+      for (User *U : RdxVal->users())
+        if (getRdxKind(U) == RdxKind)
+          return cast<Instruction>(U);
+      return cast<Instruction>(RdxVal);
+    };
     auto EvaluateScalarCost =
         [&](function_ref<InstructionCost(Instruction *)> GenCostFn) {
           InstructionCost Cost = 0;
@@ -30559,7 +30572,7 @@ class HorizontalReduction {
           for (auto [Idx, RdxVal] : enumerate(ReducedVals)) {
             if (!isa<Instruction>(RdxVal))
               continue;
-            Instruction *RdxOp = ReducedValsToOps[ReducedVals[Idx]].front();
+            Instruction *RdxOp = GetReductionOp(RdxVal);
             if (Cnt == 1) {
               unsigned SameValueCount = SameValuesCounter.lookup(RdxVal);
               Cost +=
@@ -30639,7 +30652,7 @@ class HorizontalReduction {
                   RdxOpcode, VecTy, CostKind,
                   TTI::getOperandInfo(ReducedVals[I]),
                   TTI::getOperandInfo(ReducedVals[I + 1]), {},
-                  ReducedValsToOps[ReducedVals[I]].front());
+                  GetReductionOp(ReducedVals[I]));
             }
           } else {
             Type *RedTy = VectorTy->getElementType();
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/reduced-value-replace-extractelement-cost.ll b/llvm/test/Transforms/SLPVectorizer/X86/reduced-value-replace-extractelement-cost.ll
new file mode 100644
index 0000000000000..3089a72ef5f79
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/reduced-value-replace-extractelement-cost.ll
@@ -0,0 +1,61 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S --passes=slp-vectorizer < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+
+define i32 @test(i32 %arg) {
+; CHECK-LABEL: define i32 @test(
+; CHECK-SAME: i32 [[ARG:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <4 x i32> <i32 0, i32 poison, i32 0, i32 0>, i32 [[ARG]], i32 1
+; CHECK-NEXT:    [[TMP1:%.*]] = srem <4 x i32> [[TMP0]], splat (i32 46337)
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt <4 x i32> [[TMP1]], zeroinitializer
+; CHECK-NEXT:    [[TMP3:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> zeroinitializer, <4 x i32> zeroinitializer
+; CHECK-NEXT:    [[TMP4:%.*]] = mul <4 x i32> [[TMP3]], zeroinitializer
+; CHECK-NEXT:    [[TMP5:%.*]] = urem <4 x i32> [[TMP4]], splat (i32 46337)
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp ult <4 x i32> [[TMP5]], zeroinitializer
+; CHECK-NEXT:    [[TMP7:%.*]] = select <4 x i1> [[TMP6]], <4 x i32> zeroinitializer, <4 x i32> zeroinitializer
+; CHECK-NEXT:    [[TMP8:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> <i32 0, i32 0, i32 0, i32 poison>, <4 x i32> <i32 4, i32 5, i32 6, i32 1>
+; CHECK-NEXT:    [[TMP9:%.*]] = sub <4 x i32> [[TMP8]], zeroinitializer
+; CHECK-NEXT:    [[RDX_OP:%.*]] = add <4 x i32> [[TMP7]], [[TMP9]]
+; CHECK-NEXT:    [[TMP10:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[RDX_OP]])
+; CHECK-NEXT:    ret i32 [[TMP10]]
+;
+entry:
+  %rem943.i = srem i32 0, 46337
+  %rem945.cmp.i = icmp slt i32 %rem943.i, 0
+  %rem945.i = select i1 %rem945.cmp.i, i32 0, i32 0
+  %mul946.i = mul i32 %rem945.i, 0
+  %rem947.i = urem i32 %mul946.i, 46337
+  %rem943.i.1 = srem i32 %arg, 46337
+  %rem945.cmp.i.1 = icmp slt i32 %rem943.i.1, 0
+  %rem945.i.1 = select i1 %rem945.cmp.i.1, i32 0, i32 0
+  %mul946.i.1 = mul i32 %rem945.i.1, 0
+  %rem947.i.1 = urem i32 %mul946.i.1, 46337
+  %rem956.cmp.i.1 = icmp ult i32 %rem947.i.1, 0
+  %rem956.v.i.1 = select i1 %rem956.cmp.i.1, i32 0, i32 0
+  %.neg = sub i32 0, 0
+  %rem956.cmp.i = icmp ult i32 %rem947.i, 0
+  %rem956.v.i = select i1 %rem956.cmp.i, i32 0, i32 0
+  %0 = add i32 %.neg, %rem956.v.i
+  %rem943.i.2 = srem i32 0, 46337
+  %rem945.cmp.i.2 = icmp slt i32 %rem943.i.2, 0
+  %rem945.i.2 = select i1 %rem945.cmp.i.2, i32 0, i32 0
+  %mul946.i.2 = mul i32 %rem945.i.2, 0
+  %rem947.i.2 = urem i32 %mul946.i.2, 46337
+  %rem956.cmp.i.2 = icmp ult i32 %rem947.i.2, 0
+  %rem956.v.i.2 = select i1 %rem956.cmp.i.2, i32 0, i32 0
+  %1 = add i32 %rem956.v.i.1, %0
+  %2 = add i32 %rem943.i.1, %1
+  %3 = add i32 %rem956.v.i.2, %2
+  %rem943.i.3 = srem i32 0, 46337
+  %rem945.cmp.i.3 = icmp slt i32 %rem943.i.3, 0
+  %rem945.i.3 = select i1 %rem945.cmp.i.3, i32 0, i32 0
+  %mul946.i.3 = mul i32 %rem945.i.3, 0
+  %rem947.i.3 = urem i32 %mul946.i.3, 46337
+  %rem956.cmp.i.3 = icmp ult i32 %rem947.i.3, 0
+  %rem956.v.i.3 = select i1 %rem956.cmp.i.3, i32 0, i32 0
+  %.neg38 = sub i32 0, 0
+  %4 = add i32 %3, 0
+  %5 = add i32 %.neg38, %4
+  %6 = add i32 %rem956.v.i.3, %5
+  ret i32 %6
+}

``````````

</details>


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


More information about the llvm-commits mailing list