Skip to content

[MLIR][Vector] Fix crash in foldDenseElementsAttrDestInsertOp on poison index#188508

Merged
joker-eph merged 2 commits into
llvm:mainfrom
joker-eph:fix/issue-188404
Mar 28, 2026
Merged

[MLIR][Vector] Fix crash in foldDenseElementsAttrDestInsertOp on poison index#188508
joker-eph merged 2 commits into
llvm:mainfrom
joker-eph:fix/issue-188404

Conversation

@joker-eph

Copy link
Copy Markdown
Contributor

When a dynamic index of -1 (the kPoisonIndex sentinel) was folded into the static position of a vector.insert op, foldDenseElementsAttrDestInsertOp would proceed to call calculateInsertPosition, which returned -1. The subsequent iterator arithmetic (allValues.begin() + (-1)) was undefined behaviour, causing an assertion in DenseElementsAttr::get.

Fix by bailing out early in foldDenseElementsAttrDestInsertOp when any static position equals kPoisonIndex, consistent with how InsertChainFullyInitialized already guards this case.

Fixes #188404

Assisted-by: Claude Code

…on index

When a dynamic index of -1 (the kPoisonIndex sentinel) was folded into
the static position of a vector.insert op, foldDenseElementsAttrDestInsertOp
would proceed to call calculateInsertPosition, which returned -1. The
subsequent iterator arithmetic (allValues.begin() + (-1)) was undefined
behaviour, causing an assertion in DenseElementsAttr::get.

Fix by bailing out early in foldDenseElementsAttrDestInsertOp when any
static position equals kPoisonIndex, consistent with how
InsertChainFullyInitialized already guards this case.

Fixes llvm#188404

Assisted-by: Claude Code
@llvmbot

llvmbot commented Mar 25, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-mlir-vector

@llvm/pr-subscribers-mlir

Author: Mehdi Amini (joker-eph)

Changes

When a dynamic index of -1 (the kPoisonIndex sentinel) was folded into the static position of a vector.insert op, foldDenseElementsAttrDestInsertOp would proceed to call calculateInsertPosition, which returned -1. The subsequent iterator arithmetic (allValues.begin() + (-1)) was undefined behaviour, causing an assertion in DenseElementsAttr::get.

Fix by bailing out early in foldDenseElementsAttrDestInsertOp when any static position equals kPoisonIndex, consistent with how InsertChainFullyInitialized already guards this case.

Fixes #188404

Assisted-by: Claude Code


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

2 Files Affected:

  • (modified) mlir/lib/Dialect/Vector/IR/VectorOps.cpp (+5)
  • (modified) mlir/test/Dialect/Vector/canonicalize.mlir (+19)
diff --git a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
index 73632875ca9e2..5c8c2417bfaa6 100644
--- a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
+++ b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
@@ -3763,6 +3763,11 @@ foldDenseElementsAttrDestInsertOp(InsertOp insertOp, Attribute srcAttr,
       !insertOp->hasOneUse())
     return {};
 
+  // Bail out on poison indices (kPoisonIndex = -1) to avoid computing an
+  // invalid (negative) linearized position which would cause UB below.
+  if (is_contained(insertOp.getStaticPosition(), InsertOp::kPoisonIndex))
+    return {};
+
   // Calculate the linearized position for inserting elements.
   int64_t insertBeginPosition =
       calculateInsertPosition(destTy, insertOp.getStaticPosition());
diff --git a/mlir/test/Dialect/Vector/canonicalize.mlir b/mlir/test/Dialect/Vector/canonicalize.mlir
index e2045fc526ec1..341f044b5112f 100644
--- a/mlir/test/Dialect/Vector/canonicalize.mlir
+++ b/mlir/test/Dialect/Vector/canonicalize.mlir
@@ -3807,6 +3807,25 @@ func.func @insert_vector_poison_idx_non_cst(%a: vector<4x5xf32>, %b: vector<5xf3
 
 // -----
 
+// Similar to the test above, but now the destination is a dense constant.
+// foldDenseElementsAttrDestInsertOp must not crash when the dynamic index
+// constant is -1 (the poison sentinel). Instead it should fold to ub.poison.
+// Regression test for https://github.com/llvm/llvm-project/issues/188404
+
+// CHECK-LABEL: @insert_scalar_poison_idx_dense_dest
+func.func @insert_scalar_poison_idx_dense_dest() -> vector<2xf16> {
+  // CHECK-NEXT: %[[UB:.*]] = ub.poison : vector<2xf16>
+  //  CHECK-NOT: vector.insert
+  // CHECK-NEXT: return %[[UB]] : vector<2xf16>
+  %cst = arith.constant dense<0.0> : vector<2xf16>
+  %idx = arith.constant -1 : index
+  %val = arith.constant 2.5 : f16
+  %0 = vector.insert %val, %cst [%idx] : f16 into vector<2xf16>
+  return %0 : vector<2xf16>
+}
+
+// -----
+
 // Similar to test above, but now the index is out-of-bounds.
 
 // CHECK-LABEL: @no_fold_insert_scalar_idx_oob

@banach-space banach-space left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, LGTM % optional nit

Comment thread mlir/test/Dialect/Vector/canonicalize.mlir Outdated
Co-authored-by: Andrzej Warzyński <andrzej.warzynski@gmail.com>
@joker-eph joker-eph enabled auto-merge (squash) March 28, 2026 09:48
@joker-eph joker-eph merged commit 00c6b4d into llvm:main Mar 28, 2026
10 checks passed
Aadarsh-Keshri pushed a commit to Aadarsh-Keshri/llvm-project that referenced this pull request Mar 28, 2026
…on index (llvm#188508)

When a dynamic index of -1 (the kPoisonIndex sentinel) was folded into
the static position of a vector.insert op,
foldDenseElementsAttrDestInsertOp would proceed to call
calculateInsertPosition, which returned -1. The subsequent iterator
arithmetic (allValues.begin() + (-1)) was undefined behaviour, causing
an assertion in DenseElementsAttr::get.

Fix by bailing out early in foldDenseElementsAttrDestInsertOp when any
static position equals kPoisonIndex, consistent with how
InsertChainFullyInitialized already guards this case.

Fixes llvm#188404

Assisted-by: Claude Code
fzou1 pushed a commit to fzou1/llvm-project that referenced this pull request Mar 30, 2026
…on index (llvm#188508)

When a dynamic index of -1 (the kPoisonIndex sentinel) was folded into
the static position of a vector.insert op,
foldDenseElementsAttrDestInsertOp would proceed to call
calculateInsertPosition, which returned -1. The subsequent iterator
arithmetic (allValues.begin() + (-1)) was undefined behaviour, causing
an assertion in DenseElementsAttr::get.

Fix by bailing out early in foldDenseElementsAttrDestInsertOp when any
static position equals kPoisonIndex, consistent with how
InsertChainFullyInitialized already guards this case.

Fixes llvm#188404

Assisted-by: Claude Code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[MLIR][Vector][Fold] Assertion hasSameNumElementsOrSplat failed in DenseElementsAttr::get when folding vector.insert with out-of-bounds dynamic index

3 participants