Skip to content

Conversation

SirYwell
Copy link
Member

@SirYwell SirYwell commented Aug 18, 2025

The previous approach was flawed for short and char as these are int-subtypes and truncate the result (see the backout issue https://bugs.openjdk.org/browse/JDK-8364409 for a reproducer).

This change now first ensures that the input type is small enough so no truncation gets lost when dropping the operations.

The previous implementation also used an InvolutionNode superclass with one Identity(...) implementation, but there were some reservations whether this is the right way to go. As we now have a ReverseBytesNode, there is also less benefit in having the supertype, as this covers 4 in 1 already.

I also added test cases on top of the original ones that ensure the nodes stay when we can't prove the input type is small enough.


Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Issue

  • JDK-8364407: [REDO] Consolidate Identity of self-inverse operations (Enhancement - P4)

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/26823/head:pull/26823
$ git checkout pull/26823

Update a local copy of the PR:
$ git checkout pull/26823
$ git pull https://git.openjdk.org/jdk.git pull/26823/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 26823

View PR using the GUI difftool:
$ git pr show -t 26823

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/26823.diff

Using Webrev

Link to Webrev Comment

}

@Test
@IR(counts = {IRNode.REVERSE_BYTES_S, "2"})
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is fine. The intrinsics might not apply to all platforms, in which case this would fail I think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only case I can immediately think of is riscv without -XX:+UseZbb. But you can easily disable the test for that platform.

@bridgekeeper
Copy link

bridgekeeper bot commented Aug 18, 2025

👋 Welcome back hgreule! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Aug 18, 2025

❗ This change is not yet ready to be integrated.
See the Progress checklist in the description for automated requirements.

@openjdk openjdk bot changed the title 8364407 8364407: [REDO] Consolidate Identity of self-inverse operations Aug 18, 2025
@openjdk
Copy link

openjdk bot commented Aug 18, 2025

@SirYwell The following label will be automatically applied to this pull request:

  • hotspot-compiler

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added hotspot-compiler [email protected] rfr Pull request is ready for review labels Aug 18, 2025
@mlbridge
Copy link

mlbridge bot commented Aug 18, 2025

Webrevs

Copy link
Contributor

@mhaessig mhaessig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for noticing the bug and improving your original PR, @SirYwell! I like your new approach without a superclass and your extensive testing of all edge cases and random values. Nice work!

However, I do have some questions below.

Comment on lines +39 to +40
* @summary Test that Identity simplifications of Involution nodes are being performed as expected.
* @library /test/lib /
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @summary Test that Identity simplifications of Involution nodes are being performed as expected.
* @library /test/lib /
* @summary Test that Identity simplifications of Involution nodes are being performed as expected.
* @key randomness
* @library /test/lib /

Since you are using random inputs.

Comment on lines +2076 to +2080
// Operations on sub-int types might not be "real" involutions for values outside their type range.
// Make sure not to drop potential truncations.
if (type == nullptr || involution->bottom_type()->is_int()->contains(type)) {
return involution->in(1)->in(1);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of skipping the optimization, could you "clean" involution->in(1)->in(1) using mask_int_value()? That would follow the semantics of JVMS§6.5 ireturn.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would need to happen in Ideal() then instead. Doing that would work too, but it further complicates things with little benefits imo.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you not testing involution on NegL/I nodes? Can this not be optimized?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NegL/I aren't used currently (see e.g. https://bugs.openjdk.org/browse/JDK-8262346).

Copy link
Member

@jaskarth jaskarth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks nice! I've just left some style comments.

static Node* simplify_involution(PhaseGVN* phase, Node* involution) {
if (involution->in(1)->Opcode() == involution->Opcode()) {
Node* original = involution->in(1)->in(1);
const TypeInt *type = phase->type(original)->isa_int();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const TypeInt *type = phase->type(original)->isa_int();
const TypeInt* type = phase->type(original)->isa_int();

Comment on lines +131 to +132

}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an extra whitespace:

Suggested change
}
}

if (involution->in(1)->Opcode() == involution->Opcode()) {
Node* original = involution->in(1)->in(1);
const TypeInt *type = phase->type(original)->isa_int();
// Operations on sub-int types might not be "real" involutions for values outside their type range.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be helpful to state an example of the disallowed case in the comment, maybe something like:

Suggested change
// Operations on sub-int types might not be "real" involutions for values outside their type range.
// Operations on sub-int types might not be "real" involutions for values outside their type range, for example a ReverseBytesS node with an input larger than short.

@SirYwell SirYwell marked this pull request as draft August 19, 2025 08:27
@openjdk openjdk bot removed the rfr Pull request is ready for review label Aug 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

3 participants