[vector] RFR 8221816: IndexOutOfBoundsException for fromArray/intoArray with unset mask lanes - was: RE: IndexOutOfBoundsException with unset mask lanes
John Rose
john.r.rose at oracle.com
Thu May 30 18:36:37 UTC 2019
On May 30, 2019, at 8:42 AM, Vladimir Ivanov <vladimir.x.ivanov at oracle.com> wrote:
>
> Kishor did some experiments with masked memory operations, so I'd like to hear his thoughts on the patch.
I have a sketch of masked memory operations also.
The non-gather reads are all unmasked and apply
masking after the fact using blend.
I have an accurate mask-sensitive range-check
operation also. The spec simply says "if any lane
N corresponds an OOB array element, you get an
exception". Nothing global like "offset >= 0" is
needed or (IMO) wanted.
That's all I have right now. My versions of the
masked stores all go scalar (slow).
For masked memory operations I think we should
consider using a 2-axis scatter, where one axis
selects an array and the other axis selects an
element in the array. This is (as I have said in
the past) an inherently useful addressing form.
And for masked stores, you simply set up a
small bit-bucket array, and route all unset
lanes through a gather/scatter index that
addresses an element of the bit-bucket array.
Maybe something like this:
public void intoArray($type$[][] bases,
IntVector axis1,
IntVector axis2);
// stores this[N] into bases[i][j] where
// i = axis1[N] and j = axis2[N]
Or maybe with extra indirections:
public void intoArray($type$[][] bases,
IntVector axis1,
int[][] baseMap, int baseMapOffset,
IntVector axis2,
int[] indexMap, int indexMapOffset);
Then a masked scatter can use a bit-bucket:
$type$[][] basesPlus = Arrays.copyOf(bases, bases.length+1);
$type$[] bitBucket = new $type$[v.length()];
basesPlus[bases.length] = bitBucket;
IntVector axis1Plus = broadcast(bases.length).blend(axis1, m);
IntVector axis2Plus = broadcast(0).blend(axis2, m);
The masked store (non-scatter) is just this:
$type$[] bitBucket = new $type$[v.length()];
$type$[][] bases { a, bitBucket };
IntVector axis1 = broadcast(1).blend(broadcast(0), m);
IntVector axis2 = broadcast(0).blend(indexes, m);
Underneath the safe 2-axis array store would be an
unsafe vectorized addressing mode:
private void intoArray(Object bases,
LongVector axis1,
LongVector axis2);
// stores this[N] into unsafe(oop,j) where
// oop = unsafe(bases,i), i = axis1[N],
// j = axis2[N], and unsafe(b,n) is an
//appropriately typed unsafe memory
// reference at base b and long offset n.
That would be the compiler intrinsic. It must
operate atomically with respect to the GC.
During the internal states of the intrinsic, the
vector unit will manipulate a vector of oops,
as the intermediate result of unsafe(bases,i)
which input to unsafe(oop,j).
— John
More information about the panama-dev
mailing list