[llvm] [LLVM][LangRef] Redefine out-of-range stepvector values as being truncated. (PR #173494)

Paul Walker via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 24 06:33:47 PST 2025


https://github.com/paulwalker-arm updated https://github.com/llvm/llvm-project/pull/173494

>From c8f48b5bc34a82c6d6eab03794d8d6ee79a1a0dd Mon Sep 17 00:00:00 2001
From: Paul Walker <paul.walker at arm.com>
Date: Wed, 24 Dec 2025 13:47:51 +0000
Subject: [PATCH 1/2] [LLVM][LangRef] Redefine out-of-range stepvector values
 as being truncated.

The LangRef current defines out-of-range stepvector values as poison.
This property is at odds with both the expansion used for fixed-length
vectors and the equivalent ISD node, both of which implicitly truncate
out-of-range values.

NOTE: In order to keep the PR mostly NFC I would like to defer the
follow extensions to seperate PRs.

1) The new definition means the "8-bit" restriction can be lifted
   because that only existed due to problematic cases like
   `<vscale x n x i1> stepvector()`, which by definition is mostly poison.
   Defering because I'm unsure of the code generation support for
   smaller types, as a minimum we're missing test coverage.

2) The instcombine can fire in many more case, and the current constant
   handling can be a simplification rather than a combine.
---
 llvm/docs/LangRef.rst                                     | 2 +-
 llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp  | 2 +-
 llvm/test/Transforms/InstCombine/vscale_extractelement.ll | 7 +++++--
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index d99280f05e73f..5b462b87acb0f 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -20828,7 +20828,7 @@ of integers whose elements contain a linear sequence of values starting from 0
 with a step of 1. This intrinsic can only be used for vectors with integer
 elements that are at least 8 bits in size. If the sequence value exceeds
 the allowed limit for the element type then the result for that lane is
-a poison value.
+truncated.
 
 These intrinsics work for both fixed and scalable vectors. While this intrinsic
 supports all vector types, the recommended way to express this operation for
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
index 98e2d9ebe4fc2..f5e8d341e3493 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
@@ -448,7 +448,7 @@ Instruction *InstCombinerImpl::visitExtractElementInst(ExtractElementInst &EI) {
         if (IndexC->getValue().getActiveBits() <= BitWidth)
           Idx = ConstantInt::get(Ty, IndexC->getValue().zextOrTrunc(BitWidth));
         else
-          Idx = PoisonValue::get(Ty);
+          return nullptr;
         return replaceInstUsesWith(EI, Idx);
       }
     }
diff --git a/llvm/test/Transforms/InstCombine/vscale_extractelement.ll b/llvm/test/Transforms/InstCombine/vscale_extractelement.ll
index 9ac8a92abb689..ec58307a253d1 100644
--- a/llvm/test/Transforms/InstCombine/vscale_extractelement.ll
+++ b/llvm/test/Transforms/InstCombine/vscale_extractelement.ll
@@ -214,12 +214,15 @@ entry:
   ret i64 %1
 }
 
-; Check that poison is returned when the extracted element has wrapped.
+; TODO: stepvector now wraps rather than poisons elements when the value does
+; not fit, so this should return 0.
 
 define i8 @ext_lane256_from_stepvec() {
 ; CHECK-LABEL: @ext_lane256_from_stepvec(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i8 poison
+; CHECK-NEXT:    [[TMP0:%.*]] = call <vscale x 512 x i8> @llvm.stepvector.nxv512i8()
+; CHECK-NEXT:    [[TMP1:%.*]] = extractelement <vscale x 512 x i8> [[TMP0]], i64 256
+; CHECK-NEXT:    ret i8 [[TMP1]]
 ;
 entry:
   %0 = call <vscale x 512 x i8> @llvm.stepvector.nxv512i8()

>From 1f351807a9616182d64b62cd4db28c9da64a79c1 Mon Sep 17 00:00:00 2001
From: Paul Walker <paul.walker at arm.com>
Date: Wed, 24 Dec 2025 14:33:00 +0000
Subject: [PATCH 2/2] Update comment removing reference to out-of-range values
 being undefined.

---
 llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
index f5e8d341e3493..4dcd9751ad0f5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
@@ -444,7 +444,8 @@ Instruction *InstCombinerImpl::visitExtractElementInst(ExtractElementInst &EI) {
         unsigned BitWidth = Ty->getIntegerBitWidth();
         Value *Idx;
         // Return index when its value does not exceed the allowed limit
-        // for the element type of the vector, otherwise return undefined.
+        // for the element type of the vector.
+        // TODO: Truncate out-of-range values.
         if (IndexC->getValue().getActiveBits() <= BitWidth)
           Idx = ConstantInt::get(Ty, IndexC->getValue().zextOrTrunc(BitWidth));
         else



More information about the llvm-commits mailing list