Skip to content

Conversation

@rwestrel
Copy link
Contributor

@rwestrel rwestrel commented Apr 10, 2025

This is a variant of 8332827. In 8332827, an array access becomes
dependent on a range check CastII for another array access. When,
after loop opts are over, that RC CastII was removed, the array
access could float and an out of bound access happened. With the fix
for 8332827, RC CastIIs are no longer removed.

With this one what happens is that some transformations applied after
loop opts are over widen the type of the RC CastII. As a result, the
type of the RC CastII is no longer narrower than that of its input,
the CastII is removed and the dependency is lost.

There are 2 transformations that cause this to happen:

  • after loop opts are over, the type of the CastII nodes are widen
    so nodes that have the same inputs but a slightly different type can
    common.

  • When pushing a CastII through an Add, if of the type both inputs
    of the Adds are non constant, then we end up widening the type
    (the resulting Add has a type that's wider than that of the
    initial CastII).

There are already 3 types of Cast nodes depending on the
optimizations that are allowed. Either the Cast is floating
(depends_only_test() returns true) or pinned. Either the Cast
can be removed if it no longer narrows the type of its input or
not. We already have variants of the CastII:

  • if the Cast can float and be removed when it doesn't narrow the type
    of its input.

  • if the Cast is pinned and be removed when it doesn't narrow the type
    of its input.

  • if the Cast is pinned and can't be removed when it doesn't narrow
    the type of its input.

What we need here, I think, is the 4th combination:

  • if the Cast can float and can't be removed when it doesn't narrow
    the type of its input.

Anyway, things are becoming confusing with all these different
variants named in ways that don't always help figure out what
constraints one of them operate under. So I refactored this and that's
the biggest part of this change. The fix consists in marking Cast
nodes when their type is widen in a way that prevents them from being
optimized out.

Tobias ran performance testing with a slightly different version of
this change and there was no regression.


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-8354282: C2: more crashes in compiled code because of dependency on removed range check CastIIs (Bug - P3)(⚠️ The fixVersion in this issue is [26] but the fixVersion in .jcheck/conf is 27, a new backport will be created when this pr is integrated.)

Reviewers

Reviewing

Using git

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

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

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 24575

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

Using diff file

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

Using Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Apr 10, 2025

👋 Welcome back roland! 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 Apr 10, 2025

@rwestrel This change is no longer ready for integration - check the PR body for details.

@rwestrel rwestrel marked this pull request as ready for review April 10, 2025 15:17
@openjdk
Copy link

openjdk bot commented Apr 10, 2025

@rwestrel 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 hotspot-compiler-dev@openjdk.org rfr Pull request is ready for review labels Apr 10, 2025
@mlbridge
Copy link

mlbridge bot commented Apr 10, 2025

@merykitty
Copy link
Member

If a CastII that does not narrow its input has its type being a constant, do you think GVN should transform it into a constant, or such nodes should return the bottom type so that it is not folded into a floating ConNode?

Copy link
Contributor

@eme64 eme64 left a comment

Choose a reason for hiding this comment

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

@rwestrel thanks for looking into this one!

I have not yet deeply studied the PR, but am feeling some confusion about the naming.

I think the DependencyType is really a good step into the right direction, it helps clean things up.

I'm wondering if we should pick either depends_only_on_test or pinned, and use it everywhere consistently. Having both around as near synonymes (antonymes?) is a bit confusing for me.

I'll look into the code more later.

Comment on lines 36 to 39
const ConstraintCastNode::DependencyType ConstraintCastNode::RegularDependency(true, true, "regular dependency"); // not pinned, narrows type
const ConstraintCastNode::DependencyType ConstraintCastNode::WidenTypeDependency(true, false, "widen type dependency"); // not pinned, doesn't narrow type
const ConstraintCastNode::DependencyType ConstraintCastNode::StrongDependency(false, true, "strong dependency"); // pinned, narrows type
const ConstraintCastNode::DependencyType ConstraintCastNode::UnconditionalDependency(false, false, "unconditional dependency"); // pinned, doesn't narrow type
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there really a good reason to have the names Regular, WidenType, Strong and Unconditional? Did we just get used to these names over time, or do they really have a good reason for existance. They just don't really mean that much to me. Calling them (non)pinned and (non)narrowing would make more sense to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So NonPinnedNarrowingDependency, NonPinnedNonNarrowingDependeny, PinnedNarrowingDependency and NonPinnedNonNarrowingDependency?

Or to avoid using a negation for the one that's the weakest dependency:

FloatingNarrowingDependency, FloatingNonNarrowingDependency, NonFloatingNarrowingDependency and NonFloatingNonNarrowingDependency ?

What do you think @eme64 ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Either of these sound great :)

Comment on lines 56 to 58
bool depends_only_on_test() const {
return _depends_only_on_test;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this synonimous to non_pinning? Might that be more descriptive?

Comment on lines 90 to 91
const bool _depends_only_on_test; // Does this Cast depends on its control input or is it pinned?
const bool _narrows_type; // Does this Cast narrows the type i.e. if input type is narrower can it be removed?
Copy link
Contributor

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 good to have a really strong definition of these two, because everything else depends on it.

I would recommend to either use depends_only_on_test as the "primary" word here, or else pinned. But then try to consistently use the chosen one everywhere. Just to avoid confusion with these near synonymes.

It may also be helpful to have an example for each of the 4 combinations, just as an illustration of your definitions.

@rwestrel
Copy link
Contributor Author

If a CastII that does not narrow its input has its type being a constant, do you think GVN should transform it into a constant, or such nodes should return the bottom type so that it is not folded into a floating ConNode?

The current patch constant folds the CastII in that case. I could write a test case where that's an issue (it causes an out of bound load to float above the range check it depends on). I'm working on an update to the patch to address this.

@rwestrel
Copy link
Contributor Author

@emea thanks for the comments. As mentioned in another comment, I'm in the process of reworking the patch.

I'm wondering if we should pick either depends_only_on_test or pinned, and use it everywhere consistently. Having both around as near synonymes (antonymes?) is a bit confusing for me.

depends_only_on_test comes from Node::depends_only_on_test.

@TobiHartmann
Copy link
Member

Just wondering, since we are getting closer to RDP 1 for JDK 25 (June 05, 2025), should we defer this to JDK 26?

@rwestrel
Copy link
Contributor Author

Just wondering, since we are getting closer to RDP 1 for JDK 25 (June 05, 2025), should we defer this to JDK 26?

Deferring makes sense. This is a corner case anyway. I've been reworking the patch and it's getting more complicated so it will likely need more time for reviews.

@TobiHartmann
Copy link
Member

Sounds good, I'll defer it to JDK 26 then. Thanks for the quick reply!

@openjdk
Copy link

openjdk bot commented May 13, 2025

@rwestrel this pull request can not be integrated into master due to one or more merge conflicts. To resolve these merge conflicts and update this pull request you can run the following commands in the local repository for your personal fork:

git checkout JDK-8354282
git fetch https://git.openjdk.org/jdk.git master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push

@openjdk openjdk bot added the merge-conflict Pull request has merge conflict with target branch label May 13, 2025
@bridgekeeper
Copy link

bridgekeeper bot commented Jun 10, 2025

@rwestrel This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply issue a /touch or /keepalive command to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration!

@bridgekeeper
Copy link

bridgekeeper bot commented Jul 8, 2025

@rwestrel This pull request has been inactive for more than 8 weeks and will now be automatically closed. If you would like to continue working on this pull request in the future, feel free to reopen it! This can be done using the /open pull request command.

@bridgekeeper bridgekeeper bot closed this Jul 8, 2025
@rwestrel
Copy link
Contributor Author

rwestrel commented Jul 8, 2025

/keepalive

@openjdk
Copy link

openjdk bot commented Jul 8, 2025

@rwestrel This command can only be used in open pull requests.

@rwestrel
Copy link
Contributor Author

rwestrel commented Jul 8, 2025

/open

@openjdk openjdk bot reopened this Jul 8, 2025
@openjdk
Copy link

openjdk bot commented Jul 8, 2025

@rwestrel This pull request is now open

@bridgekeeper
Copy link

bridgekeeper bot commented Aug 5, 2025

@rwestrel This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply issue a /touch or /keepalive command to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration!

@bridgekeeper
Copy link

bridgekeeper bot commented Sep 2, 2025

@rwestrel This pull request has been inactive for more than 8 weeks and will now be automatically closed. If you would like to continue working on this pull request in the future, feel free to reopen it! This can be done using the /open pull request command.

@bridgekeeper bridgekeeper bot closed this Sep 2, 2025
@bridgekeeper
Copy link

bridgekeeper bot commented Oct 30, 2025

@rwestrel This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply issue a /touch or /keepalive command to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration!

Copy link
Contributor

@eme64 eme64 left a comment

Choose a reason for hiding this comment

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

@rwestrel Sorry I dropped the review on this one for a long time :/

I left quite a few comments. But on the whole I'm really happy with the direction you are taking. It's getting much clearer. I would still see some more clear explanations/comments. That way, we can make our previously implicit assumptions even more explicit :)

Comment on lines 46 to 47
if (!_dependency.narrows_type()) {
return this;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please add a code comment? I don't understand it right away :/

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe I'm slowly starting to understand... but a code comment would still help a lot here.

We are trying to find a dominating cast that has the same or narrower type, and replace with that one.
We are only allowed to do that if we have a narrowing cast, because ...

Comment on lines 89 to 92
private:
const bool _floating; // Does this Cast depends on its control input or is it pinned?
const bool _narrows_type; // Does this Cast narrows the type i.e. if input type is narrower can it be removed?
const char* _desc;
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought the hotspot convention was to usually put the fields first, at the top of the class?

Comment on lines +49 to +53
DependencyType(bool depends_on_test, bool narrows_type, const char* desc)
: _floating(depends_on_test),
_narrows_type(narrows_type),
_desc(desc) {
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you make the constructor private, and only expose the 4 static fields? That way, nobody comes to the strange idea to construct one of these themselves ;)

Copy link
Contributor

Choose a reason for hiding this comment

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

That would probably require moving the 4 static fields into this class here.
Example:
ConstraintCastNode::DependencyType::FloatingNarrowing

Just an idea. Maybe you have a different solution. But a private constructor would be great for sure.

Comment on lines 60 to 65
bool narrows_type() const {
return _narrows_type;
}
void dump_on(outputStream *st) const {
st->print("%s", _desc);
}
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
bool narrows_type() const {
return _narrows_type;
}
void dump_on(outputStream *st) const {
st->print("%s", _desc);
}
bool narrows_type() const {
return _narrows_type;
}
void dump_on(outputStream *st) const {
st->print("%s", _desc);
}

Newline for consistency with surrounding code.

Comment on lines +44 to +46
// 1- and 2- are not always applied depending on what constraint are applied to the Cast: there are cases where 1-
// and 2- apply, where neither 1- nor 2- apply and where one or the other apply. This class abstract away these
// details.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you spell it out a little more? Right now it feels a little bit like an "exercise for the reader".
For each optimization, what is required of the constraints? I think that would help the reader.
Equally: you could name why those constraints are required in the first place. Or is there some other place we could link to that already has those explanations?

if (wide_t != bottom_t) {
// Widening the type of the Cast (to allow some commoning) causes the Cast to change how it can be optimized (if
// type of its input is narrower than the Cast's type, we can't remove it to not loose the dependency).
return make_with(in(1), wide_t, _dependency.widen_type_dependency());
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
return make_with(in(1), wide_t, _dependency.widen_type_dependency());
return make_with(in(1), wide_t, _dependency.with_non_narrowing());

This may be clearer here, since non-narrowing prevents folding the cast away if the input is narrower. I like the code comment you already have though :)

Comment on lines 622 to 625
const TypeInteger* this_type = res->is_integer(bt);
if (!phase->C->post_loop_opts_phase()) {
return this_type;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Honestly, I would prefer to see this "delay to post loop opts" to be done outside of widen_type. It would just make more sense there. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

But maybe that is a refactoring for a separate RFE, and then not really worth it.

Copy link
Contributor

Choose a reason for hiding this comment

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

But conceptually, we want to say: if we are in post loop opts, then widen the types.
Now it looks like we want to widen always ... but then we check for post loop opts inside the method and bail out anyway. Not very transparent. Another idea: rename the method to widen_type_in_post_loop_opts.

Totally up to you though.

Comment on lines 119 to 122
virtual ConstraintCastNode* make_with(Node* parent, const TypeInteger* type, const DependencyType& dependency) const {
ShouldNotReachHere();
return nullptr;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This always smells like a messed up class hierarchy, when I see default methods with "not implemented". But maybe we can't do much better, and I've done similar things recently 🙈 . A short code comment could be helpful though.

Suggested change
virtual ConstraintCastNode* make_with(Node* parent, const TypeInteger* type, const DependencyType& dependency) const {
ShouldNotReachHere();
return nullptr;
}
virtual ConstraintCastNode* make_with(Node* parent, const TypeInteger* type, const DependencyType& dependency) const {
ShouldNotReachHere(); // Only implemented for CastII and CastLL
return nullptr;
}

Comment on lines 56 to 62
bool floating() const {
return _floating;
}

bool narrows_type() const {
return _narrows_type;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nits about naming:
I would prefer is_ for boolean queries. Otherwise, if I look at the names floating and pinned_dependency, I don't immediately know which one converts to a floating/non-floating, and which one is a boolean query.

Maybe pinned_dependency should be renamed to with_pinned_dependency.

Comment on lines 86 to 95
// Test commoning of Casts after loop opts when they are at the same control
@Test
@IR(counts = { IRNode.CAST_II, "2" })
public static int test3() {
int j = Objects.checkIndex(i - 3, length);
j += Objects.checkIndex(i, length);
j += Objects.checkIndex(i - 2, length);
j += Objects.checkIndex(i - 1, length);
return j;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not add an additional IR rule that checks that there are more casts before they get commoned? Just for completenes ;)

@rwestrel
Copy link
Contributor Author

@eme64 updated change should address your comments

Copy link
Member

@chhagedorn chhagedorn left a comment

Choose a reason for hiding this comment

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

Introducing a 4th dependency type looks reasonable. It's also nice to see one more refactoring in that area which makes it very expressive now. Thanks for doing that! I left some suggestions to possibly further improve the code.

// used when a floating node is sunk out of loop: we don't want the cast that forces the node to be out of loop to
// be removed in any case otherwise the sunk node floats back into the loop.
static const DependencyType NonFloatingNonNarrowing;

Copy link
Member

@chhagedorn chhagedorn Nov 26, 2025

Choose a reason for hiding this comment

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

I needed a moment to completely understand all these combinations. I rewrote the definitions in this process a little bit. Feel free to take some of it over:

    // All the possible combinations of floating/narrowing with example use cases:

    // Use case example: Range Check CastII
    // Floating: The Cast is only dependent on the single range check.
    // Narrowing: The Cast narrows the type to a positive index. If the input to the Cast is narrower, we can safely
    //            remove the cast because the array access will be safe.
    static const DependencyType FloatingNarrowing;

    // Use case example: Widening Cast nodes' types after loop opts: We want to common Casts with slightly different types.
    // Floating: These Casts only depend on the single control.
    // NonNarrowing: Even when the input type is narrower, we are not removing the Cast. Otherwise, the dependency
    //               to the single control is lost, and an array access could float above its range check because we
    //               just removed the dependency to the range check by removing the Cast. This could lead to an
    //               out-of-bounds access.
    static const DependencyType FloatingNonNarrowing;

    // Use case example: An array accesses that is no longer dependent on a single range check (e.g. range check smearing).
    // NonFloating: The array access must be pinned below all the checks it depends on. If the check it directly depends
    //              on with a control input is hoisted, we do hoist the Cast as well. If we allowed the Cast to float,
    //              we risk that the array access ends up above another check it depends on (we cannot model two control
    //              dependencies for a node in the IR). This could lead to an out-of-bounds access.
    // Narrowing: If the Cast does not narrow the input type, then it's safe to remove the cast because the array access
    //            will be safe.
    static const DependencyType NonFloatingNarrowing;

    // Use case example: Sinking nodes out of a loop
    // Non-Floating & Non-Narrowing: We don't want the Cast that forces the node to be out of loop to be removed in any
    //                               case. Otherwise, the sunk node could float back into the loop, undoing the sinking.
    //                               This Cast is only used for pinning without caring about narrowing types.
    static const DependencyType NonFloatingNonNarrowing;

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for taking it over :-)

Comment on lines +96 to +101
const DependencyType& with_pinned_dependency() const {
if (_narrows_type) {
return NonFloatingNarrowing;
}
return NonFloatingNonNarrowing;
}
Copy link
Member

Choose a reason for hiding this comment

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

Just a side note: We seem to mix the terms "(non-)pinned" with "(non-)floating" freely. Should we stick to just one? But maybe it's justified to use both depending on the situation/code context.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The patch as it is now adds some extra uses of "pinned" and "floating". What could make sense, I suppose, would be to try to use "floating"/"non floating" instead but there are so many uses of "pinned" in the code base already, and I don't see us getting rid of them, that I wonder if it would make a difference. So, I'm not too sure what to do.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, that's true. I was also unsure about whether we should stick with one or just allow both interchangeably. I guess since there are so many uses, we can just move forward with what you have now and still come back to clean it up if necessary - we can always do that.

rwestrel and others added 4 commits November 26, 2025 17:05
Co-authored-by: Christian Hagedorn <christian.hagedorn@oracle.com>
Co-authored-by: Christian Hagedorn <christian.hagedorn@oracle.com>
Co-authored-by: Christian Hagedorn <christian.hagedorn@oracle.com>
Co-authored-by: Christian Hagedorn <christian.hagedorn@oracle.com>
@openjdk openjdk bot removed the rfr Pull request is ready for review label Nov 26, 2025
@rwestrel
Copy link
Contributor Author

Introducing a 4th dependency type looks reasonable. It's also nice to see one more refactoring in that area which makes it very expressive now. Thanks for doing that! I left some suggestions to possibly further improve the code.

Thanks for the comments/suggestions. Updated change should take care of all of them.

@openjdk openjdk bot added the rfr Pull request is ready for review label Nov 27, 2025
Copy link
Member

@chhagedorn chhagedorn left a comment

Choose a reason for hiding this comment

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

Thanks for the update, it looks good to me! If @eme64 also agrees with the latest patch, we can submit some testing and then hopefully get it in right before the fork.

Comment on lines +96 to +101
const DependencyType& with_pinned_dependency() const {
if (_narrows_type) {
return NonFloatingNarrowing;
}
return NonFloatingNonNarrowing;
}
Copy link
Member

Choose a reason for hiding this comment

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

Yes, that's true. I was also unsure about whether we should stick with one or just allow both interchangeably. I guess since there are so many uses, we can just move forward with what you have now and still come back to clean it up if necessary - we can always do that.

// used when a floating node is sunk out of loop: we don't want the cast that forces the node to be out of loop to
// be removed in any case otherwise the sunk node floats back into the loop.
static const DependencyType NonFloatingNonNarrowing;

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for taking it over :-)

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Dec 2, 2025
Copy link
Contributor

@eme64 eme64 left a comment

Choose a reason for hiding this comment

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

@rwestrel Nice work! We not just only fixed the bug but made the concepts much clearer. This makes me very happy 😊


// All the possible combinations of floating/narrowing with example use cases:

// Use case example: Range Check CastII
Copy link
Member

Choose a reason for hiding this comment

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

I believe this is incorrect, a range check should be floating non-narrowing. It is only narrowing if the length of the array is a constant. It is because this cast encodes the dependency on the condition index u< length. This condition cannot be expressed in terms of Type unless length is a constant.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Range check CastII were added to protect the ConvI2L in the address expression on 64 bits. The problem there was, in some cases, that the ConvI2L would float above the range check (because ConvI2L has no control input) and could end up with an out of range input (which in turn would cause the ConvI2L to become top in places where it wasn't expected).
So CastII doesn't carry the control dependency of an array access on its range check. That dependency is carried by the MemNode which has its control input set to the range check.
What you're saying, if I understand it correctly, would be true if the CastII was required to prevent an array Load from floating. But that's not the case.

Copy link
Member

Choose a reason for hiding this comment

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

Got it, sorry I misunderstood!

Co-authored-by: Emanuel Peter <emanuel.peter@oracle.com>
@openjdk openjdk bot removed the ready Pull request is ready to be integrated label Dec 5, 2025
@rwestrel
Copy link
Contributor Author

rwestrel commented Dec 8, 2025

@merykitty @eme64 @chhagedorn thanks for the reviews
Does testing need to be run on this before I integrate?

@eme64
Copy link
Contributor

eme64 commented Dec 8, 2025

@rwestrel I'll run some testing now ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

graal graal-dev@openjdk.org hotspot hotspot-dev@openjdk.org hotspot-compiler hotspot-compiler-dev@openjdk.org rfr Pull request is ready for review shenandoah shenandoah-dev@openjdk.org

Development

Successfully merging this pull request may close these issues.

6 participants