On generalizing vector intrinsics

Lupusoru, Razvan A razvan.a.lupusoru at intel.com
Wed Nov 15 01:53:18 UTC 2017


Hi Vladimir,

Thanks so much for experimenting with reducing number of intrinsics needed. I am glad you are looking into this. I have a couple of questions:
- Is there a way to force methods like "binaryOp" to be inlined? In general, we will want all intrinsics to end up in same method in order to reduce chances of boxing.
- For approach 2, is it possible to recover the concrete instance of object (which represents Vector class) from the VM side? Will it appear as a "ConP" from PoV of compiler?
- How about instead of looking at it from Java side, looking at it from JVM side? I can think of two possibilities right now: 
    1) Create some new macros so that common methods like add can receive entries in intrinsics table for each type without additional verbosity required for each.
    2) Improve the intrinsics dispatcher so that once it sees a method like add used in VectorAPI, it disregards actual class used and tries to dispatch to intrinsic. In implementation, we recover shape and type from profile (which we do anyway).

Thanks,
--Razvan

-----Original Message-----
From: panama-dev [mailto:panama-dev-bounces at openjdk.java.net] On Behalf Of Vladimir Ivanov
Sent: Tuesday, November 14, 2017 2:57 PM
To: 'panama-dev at openjdk.java.net' <panama-dev at openjdk.java.net>
Subject: On generalizing vector intrinsics

Hi,

FYI I did a quick experiment with more generic vector intrinsics and wanted to share the first results. The motivation was to explore possible reduction in the number of intrinsics needed to support Vector API in the JVM.

The first candidates were binary arithmetic operations on vectors:

 
http://cr.openjdk.java.net/~vlivanov/panama/vector.generalized_intrinsics/

Overall, it looks promising.

It can be easily extended to masked variants (e.g., by adding additional argument for the mask and pass null for all-ones mask) and operation variants (e.g., saturated add).

Dispatching is simple on JVM side. One question is how to represent vector shape (element type + vector size). There are different options:

   (1) pass parameters explicitly (prototyped):

     Vector binaryOp(int opr, int elem, int size, Vector v1, Vector v2)

     (Int256Vector) VectorIntrinsics.binaryOp(VECTOR_OP_ADD,
                                              VECTOR_ELEM_INT,
                                              256,
                                              this,
                                              (Int256Vector)o);


   (2) pass concrete vector class and extract vector shape info from it

     Vector binaryOp(int opr, Class vector_box, Vector v1, Vector v2)


   (3) pass shape implicitly: extract the shape from the class of the first vector (always exact class):

final class Int256Vector extends IntVector<Shapes.S256Bit> { ...
     @Override
     @ForceInline
     public Int256Vector add(Vector<Integer,Shapes.S256Bit> v) {
         return (Int256Vector) VectorIntrinsics.binaryOp(VECTOR_OP_ADD,
							VECTOR_ELEM_INT,
							256,
							this,
						       (Int256Vector)v);
     }


Some considerations:

#1: explicit and trivial to extract info on C2 side. The downside is that it requires additional non-trivial steps to find exact vector box class (see get_exact_klass_for_vector_box() and 
ctx->find_klass(vector_klass_name) there): the fact that vector classes
aren't part of java.base, but jdk.incubator.vector complicates class lookup a bit.

#2: vector shape is clearly documented in the code, but requires some additional steps (or hard-coded info in the JVM) to extract different pieces.

#3: relies on implicit convention that JIT knows exact type for "this": 
that's the case if the usage is in concrete vector class and first vector argument is "this".

Personall, I'm in favor of #2, but other options look attractive as well.

Best regards,
Vladimir Ivanov


More information about the panama-dev mailing list