Skip to content

Conversation

@jdmpapin
Copy link
Contributor

This function created block constraints most of the time, but it would instead create a global constraint in the case of a constant string or a known object that's an instance of java/lang/Class.

Now it takes a boolean parameter isGlobal, which it uses to decide whether the new constraint should be a global constraint.

When called from constrainNewlyFoldedConst(), a global constraint can be created when the folding was based only on global constraints, which is similar to the way we already handle integral and null constants. This change will be important for const refs (coming later), since otherwise we could create a global constraint based on the symref of a const ref load that was just folded based on a block constraint, and the load might share its value number with others, e.g. if it was originally an auto load.

When called from the VP handlers for aload and aloadi, it will now always create a block constraint. In these cases, it's tempting to try to create global constraints more often, since static and shadow loads will generally have been assigned fresh value numbers due to the possibility of concurrent writes from other threads. However, it isn't clear that it should always be safe to do so.

For example, consider a shadow that we know to be immutable (not merely final). Loads of this shadow could share a value number whenever their base addresses do. I don't know whether any shadow is currently allowed to share its value number in this way, but a truly immutable shadow should be able to. So in this scenario there could be a single value number shared by multiple loads of the immutable shadow at different points. If transformIndirectLoadChain() could improve one of them based on path-sensitive knowledge of the base address, then the resulting improved load could be observed later on in the aloadi handler, and if it created a global constraint, it would inappropriately also constrain the other load.

If that scenario were to play out with const refs (coming later), then transformIndirectLoadChain() would instead change the indirect load into a direct load, so the aload handler should be conservative as well.

This function created block constraints most of the time, but it would
instead create a global constraint in the case of a constant string or a
known object that's an instance of java/lang/Class.

Now it takes a boolean parameter isGlobal, which it uses to decide
whether the new constraint should be a global constraint.

When called from constrainNewlyFoldedConst(), a global constraint can be
created when the folding was based only on global constraints, which is
similar to the way we already handle integral and null constants. This
change will be important for const refs (coming later), since otherwise
we could create a global constraint based on the symref of a const ref
load that was just folded based on a block constraint, and the load
might share its value number with others, e.g. if it was originally an
auto load.

When called from the VP handlers for aload and aloadi, it will now
always create a block constraint. In these cases, it's tempting to try
to create global constraints more often, since static and shadow loads
will generally have been assigned fresh value numbers due to the
possibility of concurrent writes from other threads. However, it isn't
clear that it should always be safe to do so.

For example, consider a shadow that we know to be immutable (not merely
final). Loads of this shadow could share a value number whenever their
base addresses do. I don't know whether any shadow is currently allowed
to share its value number in this way, but a truly immutable shadow
should be able to. So in this scenario there could be a single value
number shared by multiple loads of the immutable shadow at different
points. If transformIndirectLoadChain() could improve one of them based
on path-sensitive knowledge of the base address, then the resulting
improved load could be observed later on in the aloadi handler, and if
it created a global constraint, it would inappropriately also constrain
the other load.

If that scenario were to play out with const refs (coming later), then
transformIndirectLoadChain() would instead change the indirect load into
a direct load, so the aload handler should be conservative as well.
@jdmpapin
Copy link
Contributor Author

@vijaysun-omr, could you please review?

@vijaysun-omr
Copy link
Contributor

Could you please say a bit more (say a couple more sentences) about

If transformIndirectLoadChain() could improve one of them based on path-sensitive knowledge of the base address, then the resulting improved load could be observed later on in the aloadi handler, and if it created a global constraint, it would inappropriately also constrain the other load.

i.e. in this situation of an immutable load that has the base address being identical, why is it inappropriate to constrain the other load ?

@vijaysun-omr
Copy link
Contributor

Jenkins build all

@jdmpapin
Copy link
Contributor Author

jdmpapin commented Feb 1, 2025

It's inappropriate to constrain the other load because the hypothetical transformation was based on path-sensitive information about the base address (a block constraint), and that information may not hold elsewhere, i.e. it may not hold at the other load, e.g.:

tmp = ...;  // unknown
if (tmp == SOME_CONSTANT) {
    ... tmp.superImmutableField ...
} else {
    ... tmp.superImmutableField ...
}

The first load (in the constant case) should be folded without affecting the other one

(Edited for brevity)

@vijaysun-omr
Copy link
Contributor

I see, the value of the field may be different on different paths depending on the base value on that path. So, while it is fixed on all those paths, the fixed value may be different.

@vijaysun-omr vijaysun-omr merged commit 987df34 into eclipse-omr:master Feb 1, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants