[vector] reducing the cast implementation

Lupusoru, Razvan A razvan.a.lupusoru at intel.com
Mon Jun 4 22:59:14 UTC 2018


Hey Paul,

I am not sure just from looking at it, but I believe it should work. Hotspot already inlines o.bitSize() and this is based on type profile. Thus technically the cast is not needed since it should know by that point what type "o" is. The only part I am unsure about is whether the call to o.getClass() gets inlined so that Hotspot intrinsification resolves the class to a "constant oop". Would you be able to do a simple cast micro and see if generated code looks still good? If yes, then you can go ahead with your change.

Thanks,
Razvan

From: Paul Sandoz [mailto:paul.sandoz at oracle.com]
Sent: Monday, June 04, 2018 3:35 PM
To: panama-dev at openjdk.java.net
Cc: Lupusoru, Razvan A <razvan.a.lupusoru at intel.com>
Subject: [vector] reducing the cast implementation

Hi,

Following on from the changes to shuffle and the restriction in cast we can reduce the cast implementation, but the direction to take likely depends on HotSpot.

The easiest approach is to change, say (note for clarity i patched up the generics and intrinsic in my code base so it differs slightly):

private <T extends Shape> Int64Vector castFromByte(ByteVector<T> o) {
    if (o.bitSize() == 64) {
        Byte64Vector so = (Byte64Vector)o;
        return VectorIntrinsics.cast(
            Byte64Vector.class, byte.class, so.length(),
            int.class, LENGTH, so,
            v -> (Int64Vector)super.cast(v)
        );
    } else if (o.bitSize() == 128) {
        Byte128Vector so = (Byte128Vector)o;
        return VectorIntrinsics.cast(
            Byte128Vector.class, byte.class, so.length(),
            int.class, LENGTH, so,
            v -> (Int64Vector)super.cast(v)
        );
    } else if (o.bitSize() == 256) {
        Byte256Vector so = (Byte256Vector)o;
        return VectorIntrinsics.cast(
            Byte256Vector.class, byte.class, so.length(),
            int.class, LENGTH, so,
            v -> (Int64Vector)super.cast(v)
        );
    } else if (o.bitSize() == 512) {
        Byte512Vector so = (Byte512Vector)o;
        return VectorIntrinsics.cast(
            Byte512Vector.class, byte.class, so.length(),
            int.class, LENGTH, so,
            v -> (Int64Vector)super.cast(v)
        );
    } else {
        throw new InternalError("Unimplemented size");
    }
}

to:


private <T extends Shape> Int64Vector castFromByte(ByteVector<T> o) {
    return VectorIntrinsics.cast(
            (Class<ByteVector<T>>) o.getClass(), byte.class, o.length(),
            int.class, LENGTH, o,
            v -> (Int64Vector)super.cast(v)
    );
}
where there is no explicit cast to the concrete vector type, but this might cause issues with HotSpot.

Otherwise a more literal approach is to provide keys and values to the template, which can be used as follows if using the same intrinsic:

#if[vectorTypeToByte]
if (o.elementType() == byte.class) {
    $vectorTypeToByte$ so = ($vectorTypeToByte$) o;
    return VectorIntrinsics.cast(
            $vectorTypeToByte$.class, byte.class, so.length(), // so.length == LENGTH
            $type$.class, LENGTH, so,
            v -> ($vectortype$) super.cast(v)
    );
}
#end[vectorTypeToByte]

In addition the cast intrinsic could be modified, only one length argument is required, and the vector type being cast to passed e.g.

    return VectorIntrinsics.cast(
            $vectorTypeToByte$.class, byte.class,
            $vectortype$, $type$.class,
            LENGTH,
            v, this,
            (vector, species) -> species.cast(vector)
  );

Thoughts?

Thanks,
Paul.


More information about the panama-dev mailing list