RFR: 8342676: Unsigned Vector Min / Max transforms [v2]

Emanuel Peter epeter at openjdk.org
Wed Jan 8 09:13:45 UTC 2025


On Tue, 7 Jan 2025 08:58:12 GMT, Jatin Bhateja <jbhateja at openjdk.org> wrote:

>> Adding following IR transforms for unsigned vector Min / Max nodes.
>> 
>> => UMinV (UMinV(a, b), UMaxV(a, b)) => UMinV(a, b)
>> => UMinV (UMinV(a, b), UMaxV(b, a)) => UMinV(a, b)
>> => UMaxV (UMinV(a, b), UMaxV(a, b)) => UMaxV(a, b)
>> => UMaxV (UMinV(a, b), UMaxV(b, a)) => UMaxV(a, b)
>> => UMaxV (a, a) => a
>> => UMinV (a, a) => a
>> 
>> New IR validation test accompanies the patch.
>> 
>> This is a follow-up PR for https://github.com/openjdk/jdk/pull/20507
>> 
>> Best Regards,
>> Jatin
>
> Jatin Bhateja has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains five additional commits since the last revision:
> 
>  - Updating copyright year of modified files
>  - Merge branch 'master' of http://github.com/openjdk/jdk into JDK-8342676
>  - Update IR transforms and tests
>  - Merge branch 'master' of http://github.com/openjdk/jdk into JDK-8342676
>  - 8342676: Unsigned Vector Min / Max transforms

Generally looks reasonable. Smaller changes like this are much easier to review, thank you for splitting it out 😊 

I started some testing, so feel free to ping me again for that.

src/hotspot/share/opto/vectornode.cpp line 2140:

> 2138: }
> 2139: 
> 2140: static Node* unsigned_min_max_xform(Node* n) {

Suggestion:

static Node* UMinMaxV_Ideal(Node* n) {

I think this is how we generally name functions when we share them between nodes of different types.

src/hotspot/share/opto/vectornode.cpp line 2162:

> 2160:   // UMax (UMin(a, b), UMax(a, b))  => UMax(a, b)
> 2161:   // UMax (UMax(a, b), UMin(b, a))  => UMax(a, b)
> 2162:   if (umin && umax) {

That looks like an implicit null check. Not allowed according to style guide:
`Do not use ints or pointers as (implicit) booleans with &&, ||, if, while. Instead, compare explicitly, i.e. if (x != 0) or if (ptr != nullptr), etc.`
https://github.com/openjdk/jdk/blob/master/doc/hotspot-style.md

src/hotspot/share/opto/vectornode.cpp line 2164:

> 2162:   if (umin && umax) {
> 2163:     if ((umin->in(1) == umax->in(1) && umin->in(2) == umax->in(2)) ||
> 2164:          (umin->in(2) == umax->in(1) && umin->in(1) == umax->in(2))) {

Suggestion:

    if ((umin->in(1) == umax->in(1) && umin->in(2) == umax->in(2)) ||
        (umin->in(2) == umax->in(1) && umin->in(1) == umax->in(2))) {

Alignment was off

src/hotspot/share/opto/vectornode.hpp line 622:

> 620:   virtual uint hash() const {
> 621:     return (uintptr_t)in(1) + (uintptr_t)in(2) + Opcode();
> 622:   }

Can you explain why you do this instead of `Node::hash`?
I think you do it so that you get the same hash if you swap the operands.
I suggest you leave a comment in the code.

test/hotspot/jtreg/compiler/vectorapi/VectorUnsignedMinMaxOperationsTest.java line 26:

> 24: /**
> 25: * @test
> 26: * @bug 8338201

Bug number does not match this RFE

test/hotspot/jtreg/compiler/vectorapi/VectorUnsignedMinMaxOperationsTest.java line 29:

> 27: * @summary Support new unsigned and saturating vector operators in VectorAPI
> 28: * @modules jdk.incubator.vector
> 29: * @requires vm.compiler2.enabled

I think you can drop that requirement.

test/hotspot/jtreg/compiler/vectorapi/VectorUnsignedMinMaxOperationsTest.java line 109:

> 107: 
> 108:     @Test
> 109:     @IR(counts = {IRNode.UMAX_VB, " >0 "}, applyIf = {"UseAVX", " >0 "})

I think we usually use CPU features, like `avx`.

test/hotspot/jtreg/compiler/vectorapi/VectorUnsignedMinMaxOperationsTest.java line 116:

> 114:                      .lanewise(VectorOperators.UMAX,
> 115:                                ByteVector.fromArray(bspec, byte_in2, i))
> 116:                      .intoArray(byte_out, i);

Suggestion:

            ByteVector.fromArray(bspec, byte_in1, i)
                      .lanewise(VectorOperators.UMAX,
                                ByteVector.fromArray(bspec, byte_in2, i))
                      .intoArray(byte_out, i);

Alignment looked off

test/hotspot/jtreg/compiler/vectorapi/VectorUnsignedMinMaxOperationsTest.java line 453:

> 451:             IntVector vec1 = IntVector.fromArray(ispec, int_in1, i);
> 452:             IntVector vec2 = IntVector.fromArray(ispec, int_in2, i);
> 453:             // UMinV (UMinV vec1, vec2) (UMaxV vec1, vec2) => UMinV vec1 vec2

I think you now always have pattern `minmax (minmax vec1, vec2) (minmax vec1, vec2)`, i.e. with `vec1` as first operand and `vec2` as second. Would be nice to have one where they are swapped:
`minmax (minmax vec1, vec2) (minmax vec2, vec1)`

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

Changes requested by epeter (Reviewer).

PR Review: https://git.openjdk.org/jdk/pull/21604#pullrequestreview-2536521746
PR Review Comment: https://git.openjdk.org/jdk/pull/21604#discussion_r1906839550
PR Review Comment: https://git.openjdk.org/jdk/pull/21604#discussion_r1906841096
PR Review Comment: https://git.openjdk.org/jdk/pull/21604#discussion_r1906844139
PR Review Comment: https://git.openjdk.org/jdk/pull/21604#discussion_r1906850212
PR Review Comment: https://git.openjdk.org/jdk/pull/21604#discussion_r1906810532
PR Review Comment: https://git.openjdk.org/jdk/pull/21604#discussion_r1906812099
PR Review Comment: https://git.openjdk.org/jdk/pull/21604#discussion_r1906818097
PR Review Comment: https://git.openjdk.org/jdk/pull/21604#discussion_r1906824451
PR Review Comment: https://git.openjdk.org/jdk/pull/21604#discussion_r1906835049


More information about the hotspot-compiler-dev mailing list