[llvm] [IR] Split vector.splice into vector.splice.down and vector.splice.up (PR #170796)

Paul Walker via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 5 04:43:48 PST 2025


================
@@ -20729,30 +20729,79 @@ Arguments:
 All arguments must be vectors of the same type whereby their logical
 concatenation matches the result type.
 
-'``llvm.vector.splice``' Intrinsic
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+'``llvm.vector.splice.down``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+This is an overloaded intrinsic.
+
+::
+
+      declare <2 x double> @llvm.vector.splice.down.v2f64(<2 x double> %vec1, <2 x double> %vec2, i32 %imm)
+      declare <vscale x 4 x i32> @llvm.vector.splice.down.nxv4i32(<vscale x 4 x i32> %vec1, <vscale x 4 x i32> %vec2, i32 %imm)
+
+Overview:
+"""""""""
+
+The '``llvm.vector.splice.down.*``' intrinsics construct a vector by
+concatenating two vectors together, shifting the elements down by ``imm``, and
+extracting the lower half.
+
+This is equivalent to :ref:`llvm.fshr.* <int_fshr>`, but operating on elements
+instead of bits.
+
+These intrinsics work for both fixed and scalable vectors. While this intrinsic
+supports all vector types the recommended way to express this operation for
+fixed-width vectors is still to use a shufflevector, as that may allow for more
+optimization opportunities.
+
+For example:
+
+.. code-block:: text
+
+ llvm.vector.splice.down(<A,B,C,D>, <E,F,G,H>, 1);
+		     ==> <A,B,C,D,E,F,G,H>
+		     ==> <B,C,D,E,F,G,H,_>
+		     ==> <B,C,D,E>
+
+
+Arguments:
+""""""""""
+
+The first two operands are vectors with the same type. The start index is imm
+modulo the runtime number of elements in the source vector. For a fixed-width
----------------
paulwalker-arm wrote:

The modulo part is not true because the "runtime number of elements" is now a valid index?

I do think we should be more cautious before introducing this flexibility, especially if the goal is to support non-immediate indices because the original definition means an `and` is sufficient to mask the index but with this change we'll need a `max` operation. Have you thought about how this change will affect operation legalisation?

Not sure, but perhaps allowing `0` for the shift.right case might also be problematic?  This is why we went the common splice route to start with because it blocked off those two scenarios.

I'm not against the change, it's just an easy IR change could end up being problematic during code generation.

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


More information about the llvm-commits mailing list