Summary
Change the behavior of the cross lane operations selectFrom
and the single vector argument accepting rearrange
to wrap shuffle indexes rather than check if the indexes are out of bounds and throw an exception.
Problem
The current behavior, throw an exception when indexes are out of bounds, is very hard to optimize and generate an efficient sequence of instructions. This impacts performance for a useful class of SIMD algorithms that use table lookups.
Solution
Wrap the shuffle indexes in the range of [0, VLENGTH - 1]
, where VLENGTH
is the length of the vector. When VLENGTH
is a power of two (for all known implementations) wrapping an index i
is the result of the expression i & (VLENGTH - 1)
.
Specification
jdk.incubator.vector: jdk.incubator.vector.Vector.rearrange(jdk.incubator.vector.VectorShuffle)
/**
* Rearranges the lane elements of this vector, selecting lanes
* under the control of a specific shuffle.
*
* This is a cross-lane operation that rearranges the lane
* elements of this vector.
*
* For each lane {@code N} of the shuffle, and for each lane
* source index {@code I=s.wrapIndex(s.laneSource(N))} in the shuffle,
* the output lane {@code N} obtains the value from
* the input vector at lane {@code I}.
*
* @param s the shuffle controlling lane index selection
* @return the rearrangement of the lane elements of this vector
* @see #rearrange(VectorShuffle,VectorMask)
* @see #rearrange(VectorShuffle,Vector)
*/
public abstract Vector<E> rearrange(VectorShuffle<E> s);
jdk.incubator.vector: jdk.incubator.vector.Vector.rearrange(jdk.incubator.vector.VectorShuffle,jdk.incubator.vector.VectorMask)
/**
* Rearranges the lane elements of this vector, selecting lanes
* under the control of a specific shuffle and a mask.
*
* This is a cross-lane operation that rearranges the lane
* elements of this vector.
*
* For each lane {@code N} of the shuffle, and for each lane
* source index {@code I=s.wrapIndex(s.laneSource(N))} in the shuffle,
* the output lane {@code N} obtains the value from
* the input vector at lane {@code I} if the mask is set.
* Otherwise the output lane {@code N} is set to zero.
*
* <p> This method returns the value of this pseudocode:
* <pre>{@code
* Vector<E> r = this.rearrange(s);
* return broadcast(0).blend(r, m);
* }</pre>
*
* @param s the shuffle controlling lane index selection
* @param m the mask controlling application of the shuffle
* @return the rearrangement of the lane elements of this vector
* @see #rearrange(VectorShuffle)
* @see #rearrange(VectorShuffle,Vector)
*/
public abstract Vector<E> rearrange(VectorShuffle<E> s, VectorMask<E> m);
jdk.incubator.vector: jdk.incubator.vector.selectFrom(jdk.incubator.vector.Vector)
/**
* Using index values stored in the lanes of this vector,
* assemble values stored in second vector {@code v}.
* The second vector thus serves as a table, whose
* elements are selected by indexes in the current vector.
*
* This is a cross-lane operation that rearranges the lane
* elements of the argument vector, under the control of
* this vector.
*
* For each lane {@code N} of this vector, and for each lane
* value {@code I=wrapIndex(this.lane(N))} in this vector,
* the output lane {@code N} obtains the value from
* the argument vector at lane {@code I}.
*
* In this way, the result contains only values stored in the
* argument vector {@code v}, but presented in an order which
* depends on the index values in {@code this}.
*
* The result is the same as the expression
* {@code v.rearrange(this.toShuffle())}.
*
* @param v the vector supplying the result values
* @return the rearrangement of the lane elements of {@code v}
* @see #rearrange(VectorShuffle)
*/
public abstract Vector<E> selectFrom(Vector<E> v);
jdk.incubator.vector: jdk.incubator.vector.selectFrom(jdk.incubator.vector.Vector,jdk.incubator.vector.VectorMask)
/**
* Using index values stored in the lanes of this vector,
* assemble values stored in second vector, under the control
* of a mask.
* Using index values stored in the lanes of this vector,
* assemble values stored in second vector {@code v}.
* The second vector thus serves as a table, whose
* elements are selected by indexes in the current vector.
* Lanes that are unset in the mask receive a
* zero rather than a value from the table.
*
* This is a cross-lane operation that rearranges the lane
* elements of the argument vector, under the control of
* this vector and the mask.
*
* The result is the same as the expression
* {@code v.rearrange(this.toShuffle(), m)}.
*
* @param v the vector supplying the result values
* @param m the mask controlling selection from {@code v}
* @return the rearrangement of the lane elements of {@code v}
* @see #selectFrom(Vector)
* @see #rearrange(VectorShuffle,VectorMask)
*/
public abstract Vector<E> selectFrom(Vector<E> v, VectorMask<E> m);
Additional Links:
https://cr.openjdk.org/~sviswanathan/CSRs/CSR_JDK_8340142/Vector.html#rearrange(jdk.incubator.vector.VectorShuffle) https://cr.openjdk.org/~sviswanathan/CSRs/CSR_JDK_8340142/Vector.html#rearrange(jdk.incubator.vector.VectorShuffle,jdk.incubator.vector.VectorMask) https://cr.openjdk.org/~sviswanathan/CSRs/CSR_JDK_8340142/Vector.html#selectFrom(jdk.incubator.vector.Vector) https://cr.openjdk.org/~sviswanathan/CSRs/CSR_JDK_8340142/Vector.html#selectFrom(jdk.incubator.vector.Vector,jdk.incubator.vector.VectorMask)
- csr of
-
JDK-8340079 Modify rearrange/selectFrom Vector API methods to perform wrapIndexes instead of checkIndexes
-
- Resolved
-