RFR: 8370691: Add new Float16Vector type and enable intrinsification of vector operations supported by auto-vectorizer

Paul Sandoz psandoz at openjdk.org
Wed Nov 12 20:13:49 UTC 2025


On Wed, 12 Nov 2025 19:48:54 GMT, Paul Sandoz <psandoz at openjdk.org> wrote:

>>> > Some quick comments.
>>> > We should be consistent in the naming, and rename `Halfloat*` to `Float16*`.
>>> 
>>> I concur, especially since there are multiple 16-bit floating-point formats in use including the IEEE 754 float16 as well as bfloat16.
>> 
>> There are nomenclature issues that I am facing. Currently, all the Float16 concrete classes use the Halffloat prefix i.e., Halffloat64Vector, Halffloat128Vector; converting these to Float16 looks a little confusing, i.e., Float1664Vector, Float16128Vector, etc Kindly suggest a better name to represent these classes.
>
>> > > Some quick comments.
>> > > We should be consistent in the naming, and rename `Halfloat*` to `Float16*`.
>> > 
>> > 
>> > I concur, especially since there are multiple 16-bit floating-point formats in use including the IEEE 754 float16 as well as bfloat16.
>> 
>> There are nomenclature issues that I am facing. Currently, all the Float16 concrete classes use the Halffloat prefix i.e., Halffloat64Vector, Halffloat128Vector; converting these to Float16 looks a little confusing, i.e., Float1664Vector, Float16128Vector, etc Kindly suggest a better name to represent these classes.
> 
> Maybe we move the shape to the end e.g., `Float16Vector128`, `IntVector128`, `IntVectorMax`?

> Hi @PaulSandoz , Thanks for your comments. Please find below my responses.
> 
> > When you generate the fallback code for unary/binary etc can you push the carrier type and conversations into the uOp/bOp implementations so you don't have to explicitly operate on the carrier type and do the conversions as you do now e.g.,:
> > ```
> > v0.uOp(m, (i, a) -> float16ToShortBits(Float16.valueOf(-(shortBitsToFloat16(($type$)a).floatValue()))));
> > ```
> 
> Currently, uOp and uOpTemplates are part of the scaffolding logic and are sacrosanct; they are shared by various abstracted vector classes, and their semantics are defined by the lambda expression. I agree that explicit conversion in lambdas looks verbose, but moving them to uOpTemplate may fracture the lambda expression such that part of its semantics, i.e,. conversions, will seep into uOpTemplate, while what will appear at the surface will be the expression operating over primitive float values; this may become very confusing.

Since the uOpTemplate etc are per element vector type it seems straightforward to adjust the template to perform the conversion before and after the function application, or add a default method to FUnOp etc that operates on the carrier value and performs the conversions and the template calls that default method. Later we will eventually be able to declare Float16![] and it should all collapse away. 

> 
> > Requiring two arguments means they can get out of sync. Previously the class provided all the information needed, now
> > arguably the type does.
> 
> Yes, from the compiler standpoint point all we care about is the carrier type, which determines the vector lane size. This is augmented with operation kind (PRIM / FP16) to differentiate a short vector lane from a float16 vector lane. Apart from this, we need to pass the VectorBox type to wrap the vector IR.

The basic type codes are declared and shared across Java and HotSpot - it's used in `LaneType`. Can we pass a single argument that is the basic type instead of two arguments. HotSpot should know from the basic type what the carrier class and also what the operation type without it being explicitly told, since presumably it knew the inverse - the basic type from the element class.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/28002#issuecomment-3523722566


More information about the core-libs-dev mailing list