RFR: 8367292: VectorAPI: Optimize VectorMask.fromLong/toLong() for SVE [v3]

Emanuel Peter epeter at openjdk.org
Tue Oct 28 08:20:04 UTC 2025


On Mon, 27 Oct 2025 06:17:10 GMT, Xiaohong Gong <xgong at openjdk.org> wrote:

>> Hi @eme64 @erifan , thanks for all your comments on this function. After a deep thinking, I think `mask_op_prefers_predicate()` is optimal. The implementation will be reverted back to the first version. Following is my consideration:
>> 
>> 1) Before my patch, what a mask is for these mask ops based on the architectures. It is distinguished just based whether the mask is a predicate type or a vector.
>>     - On architectures that support the predicate feature, the mask's type is `TypeVectMask` which denotes a predicate type. And the backend is implemented with predicate instructions and requires the predicate input/output.
>>     - On architectures that do not support the predicate feature, the original mask's type is an unpacked `TypeVect` varying from `TypeVectA` to `TypeVectZ` based on the vector length with different element data size. As these ops are special that the implementation do not have any relationship with the element width in each lane, packing the mask to 8-bit element width would be friendly to performance. Hence, in IR-level, the original vector mask will be packed with a `VectorStoreMask` before passed to these ops.
>> 
>> 2) I don't want to break current solution/idea of mask handling for these ops. In my patch, what I want to change is **using a helper function** to check whether the specified op is implemented with predicate instruction or not, **instead of** just checking the original mask type. If true, the mask is a predicate without any conversions needed. If not, the mask needs to be packed with a `VectorStoreMask`. 
>> 
>> 3) This function can also be used for other ops in future. Let backend choose how a vector mask is represented (with a predicate register or a vector register). Currently, it is clear that the mask type is defined based on whether platform supports predicate or not. But it might be the case that the performance will be better if mask is implemented with vector than predicate on a predicate supported platform. For such ops, we can also use this function to guide how the mask is represented in IR-level.
>> 
>> Changing to check whether the mask is a `packed` vector making things more confusing to me. Because it is just a temporary status of mask and special to these mask ops. We have to consider other ops that also use a vector mask. In general, the mask is represented with either an unpacked vector or a predicate.
>> 
>> Thanks,
>> Xiaohong
>
> The implementation on AArch64 would be like:
> 
> bool Matcher::mask_op_prefers_predicate(int opcode, const TypeVect* vt) {
>     // Only SVE supports the predicate feature.
>     if (UseSVE == 0) {
>       // On architectures that do not support the predicate feature, vector
>       // mask is stored in a normal vector with the type of "TypeVect" varing
>       // from "TypeVectA" to "TypeVectZ" based on the vector length in bytes.
>       // It cannot be a "TypeVectMask".
>       assert(vt->isa_vectmask() == nullptr, "mask type not match");
>       return false;
>     }
> 
>     assert(vt->isa_vectmask(), "The mask type must be a TypeVectMask on SVE");
>     switch (opcode) {
>       case Op_VectorMaskToLong:
>       case Op_VectorLongToMask:
>         // SVE does not have native predicate instructions for these two ops.
>         // Instead, they are implemented with vector instructions. Hence, to
>         // improve the performance, we prefer saving the mask in a vector as
>         // the input/output of these IRs.
>         return false;
>       default:
>         // By default, all the mask operations are implemented with predicate
>         // instructions with a predicate input/output.
>         return true;
>     }
>   }
> 
> And the comments before the helper function in matcher.hpp:
> 
>   // Identify if a vector mask operation requires the input/output mask to be
>   // saved with a predicate type (i.e. TypeVectMask) or not. Return true if it
>   // requires a predicate type. And return false if it requires a vector type.
>   static bool mask_op_prefers_predicate(int opcode, const TypeVect* vt);
> 
> 
> Is that more clear? Thanks!

Yes, these are a step int the right direction! :)

Thanks a lot for the explanations, very helpful! Please make sure that they are all represented in the code comments, so we don't lose them to this GitHub thread!

`// Identify if a vector mask operation requires the input/output mask to be`
The language of `requires` slipped again into your explanation. Is that intended? Probably not?
You should use a condensed version from your GitHub comments above, I think that would be very helpful :)

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

PR Review Comment: https://git.openjdk.org/jdk/pull/27481#discussion_r2468385896


More information about the hotspot-compiler-dev mailing list