On Thu, 13 Aug 2026 09:53:28 GMT, Quan Anh Mai <[email protected]> wrote:
>>> Since these transformations are similar between different kinds of
>>> `XorNode` (scalar, vector, mask). I suggest refactoring it to a separate
>>> function that gets called from those places.
>>
>> Thanks for the suggestion. Just to make sure I understand correctly: are you
>> proposing that we extract the `(A & B) ^ B → ~A & B` rewrite into a shared
>> helper and call it from scalar `XorI/XorL` as well as from vector/mask
>> `XorV/XorVMask`?
>>
>> If so, that is feasible for the pattern-matching part (finding the And,
>> handling commutativity, checking single-use / TOP). I prototyped that
>> briefly. The limitation is that constructing the rewritten graph does not
>> share cleanly across these cases:
>>
>> - scalar uses `XorI/L` + `AndI/L`
>>
>> - vector/mask uses `Replicate/MaskAll` + `XorV/XorVMask` + `AndV/AndVMask`
>>
>> - vector also needs extra checks that scalar does not (e.g. rejecting
>> predicated `XorV/AndV`)
>>
>> So beyond the matcher, each Ideal path still needs its own node-building
>> glue, and folding scalar into this change would expand the scope (and tests)
>> quite a bit.
>>
>> I’d prefer to keep this RFE focused on the `vector/mask` canonicalize (which
>> already shares one Ideal path for `XorV` and `XorVMask`), and file a
>> follow-up RFE for the scalar side (and any further shared-helper cleanup) if
>> that sounds reasonable to you.
>
> @erifan Thanks for your response. The issue I see is that there are a lot of
> different patterns, and each time we will just say well we only want to focus
> on vector/mask canonicalization. And with more patterns getting integrated,
> it will take us more work to consolidate the implementations between the
> vector nodes and the scalar nodes.
>
> My idea is that we will have a utility object `ArithmeticPattern` (for
> example) which can be constructed from an arithmetic node. The object will
> know what the element type is, how to create a constant, how to check whether
> a node is a constant, or if it is a particular constant. With template, the
> checks can be much easier. For example (you can probably think of a better
> way, this is just my first thought):
>
> enum class NodeTypeCon {
> INT,
> LONG,
> VECTOR
> }
>
> template <class NodeClass>
> class NodeType;
>
> template<>
> class NodeType<XorINode> {
> static constexpr NodeTypeCon value = INT;
> };
>
> template <NodeTypeCon nodeType>
> Node* create_xor(Node* op1, Node op2);
>
> template <>
> Node* create_xor<NodeTypeCon::INT>(Node* op1, Node op2) {
> return new XorINode(op1, op2);
> }
>
> This will allow us to extend these transformations easier across different
> data types, and reduce the work to implement more pattern for vector/mask
> nodes in the future.
Hi @merykitty, thanks for the suggestion — I agree it is reasonable.
Would you prefer that we expand this PR’s scope to also cover the scalar side
(`XorI` / `XorL`), or keep the current focus on vector and vector mask only?
@dean-long @theRealAph, what do you think?
-------------
PR Comment: https://git.openjdk.org/jdk/pull/32095#issuecomment-5289391600