On Mon, 15 Dec 2025 03:01:39 GMT, Eric Fang <[email protected]> wrote:
>> `VectorMaskCastNode` is used to cast a vector mask from one type to another
>> type. The cast may be generated by calling the vector API `cast` or
>> generated by the compiler. For example, some vector mask operations like
>> `trueCount` require the input mask to be integer types, so for floating
>> point type masks, the compiler will cast the mask to the corresponding
>> integer type mask automatically before doing the mask operation. This kind
>> of cast is very common.
>>
>> If the vector element size is not changed, the `VectorMaskCastNode` don't
>> generate code, otherwise code will be generated to extend or narrow the
>> mask. This IR node is not free no matter it generates code or not because it
>> may block some optimizations. For example:
>> 1. `(VectorStoremask (VectorMaskCast (VectorLoadMask x)))` The middle
>> `VectorMaskCast` prevented the following optimization: `(VectorStoremask
>> (VectorLoadMask x)) => (x)`
>> 2. `(VectorMaskToLong (VectorMaskCast (VectorLongToMask x)))`, which blocks
>> the optimization `(VectorMaskToLong (VectorLongToMask x)) => (x)`.
>>
>> In these IR patterns, the value of the input `x` is not changed, so we can
>> safely do the optimization. But if the input value is changed, we can't
>> eliminate the cast.
>>
>> The general idea of this PR is introducing an `uncast_mask` helper function,
>> which can be used to uncast a chain of `VectorMaskCastNode`, like the
>> existing `Node::uncast(bool)` function. The funtion returns the first non
>> `VectorMaskCastNode`.
>>
>> The intended use case is when the IR pattern to be optimized may contain one
>> or more consecutive `VectorMaskCastNode` and this does not affect the
>> correctness of the optimization. Then this function can be called to
>> eliminate the `VectorMaskCastNode` chain.
>>
>> Current optimizations related to `VectorMaskCastNode` include:
>> 1. `(VectorMaskCast (VectorMaskCast x)) => (x)`, see JDK-8356760.
>> 2. `(XorV (VectorMaskCast (VectorMaskCmp src1 src2 cond)) (Replicate -1)) =>
>> (VectorMaskCast (VectorMaskCmp src1 src2 ncond))`, see JDK-8354242.
>>
>> This PR does the following optimizations:
>> 1. Extends the optimization pattern `(VectorMaskCast (VectorMaskCast x)) =>
>> (x)` as `(VectorMaskCast (VectorMaskCast ... (VectorMaskCast x))) => (x)`.
>> Because as long as types of the head and tail `VectorMaskCastNode` are
>> consistent, the optimization is correct.
>> 2. Supports a new optimization pattern `(VectorStoreMask (VectorMaskCast ...
>> (VectorLoadMask x))) => (x)`. Since the value before and after the pattern
>> is a boolean vect...
>
> Eric Fang has updated the pull request incrementally with one additional
> commit since the last revision:
>
> Refine code comments
src/hotspot/share/opto/vectornode.cpp line 1062:
> 1060: if (!in1->isa_Vector()) {
> 1061: break;
> 1062: }
Can you write a comment here, why you want to avoid handling masks of type
TypeVectMask ?
src/hotspot/share/opto/vectornode.cpp line 1063:
> 1061: break;
> 1062: }
> 1063: assert(n->as_Vector()->length() == in1->as_Vector()->length(),
> "vector length must match");
While assertions are good to add, but mask cast is a lanewise operation, i.e.
length compatibility is implied, and adding an assertion for IR invariants is
redundant.
test/hotspot/jtreg/compiler/vectorapi/VectorStoreMaskIdentityTest.java line 186:
> 184: testThreeCastsKernel(IntVector.SPECIES_128,
> ShortVector.SPECIES_64, FloatVector.SPECIES_128, LongVector.SPECIES_256);
> 185: verifyResult(IntVector.SPECIES_128.length());
> 186: }
A nit, you can define final static species like S128, S64 pointing to fully
qualified species, it will reduce the verbosity.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/28313#discussion_r2618083147
PR Review Comment: https://git.openjdk.org/jdk/pull/28313#discussion_r2618086953
PR Review Comment: https://git.openjdk.org/jdk/pull/28313#discussion_r2618109644