RFR: 8315066: Add unsigned bounds and known bits to TypeInt/Long [v43]

Emanuel Peter epeter at openjdk.org
Fri Feb 14 09:46:35 UTC 2025


On Thu, 13 Feb 2025 14:59:02 GMT, Quan Anh Mai <qamai at openjdk.org> wrote:

>> Hi,
>> 
>> This patch adds unsigned bounds and known bits constraints to TypeInt and TypeLong. This opens more transformation opportunities in an elegant manner as well as helps avoid some ad-hoc rules in Hotspot.
>> 
>> In general, a `TypeInt/Long` represents a set of values `x` that satisfies: `x s>= lo && x s<= hi && x u>= ulo && x u<= uhi && (x & zeros) == 0 && (x & ones) == ones`. These constraints are not independent, e.g. an int that lies in [0, 3] in signed domain must also lie in [0, 3] in unsigned domain and have all bits but the last 2 being unset. As a result, we must canonicalize the constraints (tighten the constraints so that they are optimal) before constructing a `TypeInt/Long` instance.
>> 
>> This is extracted from #15440 , node value transformations are left for later PRs. I have also added unit tests to verify the soundness of constraint normalization.
>> 
>> Please kindly review, thanks a lot.
>> 
>> Testing
>> 
>> - [x] GHA
>> - [x] Linux x64, tier 1-4
>
> Quan Anh Mai has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 56 commits:
> 
>  - Merge branch 'master' into unsignedbounds
>  - Merge branch 'master' into unsignedbounds
>  - harden SimpleCanonicalResult
>  - number lemmas
>  - include
>  - clean up intn_t
>  - refine first_violation
>  - assignment operator
>  - exhaustive tests
>  - make con
>  - ... and 46 more: https://git.openjdk.org/jdk/compare/c2fc9478...3cd25862

Things are looking steadily better! I have a few more suggestions.

src/hotspot/share/opto/rangeinference.cpp line 149:

> 147: 
> 148:   Call r the smallest value not smaller than lo that satisfies bits. Since lo
> 149:   does not satisfy bits, lo < r (2.7)

You could reorder things to make it more straight forward:
- First define `r`:
  - the smallest value not smaller than lo that satisfies bits
- Then construct `v`
- Lemma: `v` satisfies bits (probably helpful to get started...)
- Statement: `r = v`
- Proof
  - (a): `r <= v` (using the Lemma)
  - (b): `r >= v` (via contradiction if `r < v`)

src/hotspot/share/opto/rangeinference.cpp line 153:

> 151:   a. Firstly, we prove that r <= v:
> 152: 
> 153:     Trivially, lo < v since:

Suggestion:

    We know that lo < v since:

It's a little funny to say its trivial and then go ahead and prove it 😅

src/hotspot/share/opto/rangeinference.cpp line 158:

> 156:       bits at x > i have lower significance, and are thus irrelevant
> 157: 
> 158:     As established above, the first (i + 1) bits of v satisfy bits.

Two things:
- I don't see immediately how it is true
- And we are not trying to prove that v satisfies bits here. But we should prove that somewhere, just not under section `a. Firstly, we prove that r <= v:`, right?

src/hotspot/share/opto/rangeinference.cpp line 164:

> 162: 
> 163:     As a result, v > lo and v satisfies bits since all of its bits satisfy bits. Which
> 164:     means r <= v since r is the smallest such value.

This is a little quick...
- You proved `v > lo` above, so give it a name and reference it here.
- `v satisfies bits` can be its separate step as I suggested above. Give it a name and reference it here.
- `v` is a value larger than `lo` that satisfies bits, and `r` is the smallest value larger than `lo` that satisfies bits, hence `v >= r`.

src/hotspot/share/opto/rangeinference.cpp line 166:

> 164:     means r <= v since r is the smallest such value.
> 165: 
> 166:   b. Secondly, we prove that r == v. Suppose r < v:

Suggestion:

  b. Secondly, we prove that r >= v. Suppose r < v:

src/hotspot/share/opto/rangeinference.cpp line 179:

> 177:       v[j] == 1 (according to 2.b.2)
> 178:       r[x] == v[x], for x < j (according to 2.b.3)
> 179:       v[x] == lo[x], for x < j (according to 2,4 because j < i)

Suggestion:

      v[x] == lo[x], for x < j (according to 2.4 because j < i)

src/hotspot/share/opto/rangeinference.cpp line 184:

> 182:       r[j] == 0
> 183:       lo[j] == 1
> 184:       r[x] == lo[x], for x < j

Suggestion:

      r[j] == 0    (according to 2.b.1)
      lo[j] == 1   (lo[j] == v[j] == 1, according to 2.4 because j < i, and according to 2.b.2)
      r[x] == lo[x], for x < j  (according to 2.4 because j < i)

Then you could even drop the other list above, right?

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

Changes requested by epeter (Reviewer).

PR Review: https://git.openjdk.org/jdk/pull/17508#pullrequestreview-2617160068
PR Review Comment: https://git.openjdk.org/jdk/pull/17508#discussion_r1955816531
PR Review Comment: https://git.openjdk.org/jdk/pull/17508#discussion_r1955799188
PR Review Comment: https://git.openjdk.org/jdk/pull/17508#discussion_r1955809601
PR Review Comment: https://git.openjdk.org/jdk/pull/17508#discussion_r1955828802
PR Review Comment: https://git.openjdk.org/jdk/pull/17508#discussion_r1955832072
PR Review Comment: https://git.openjdk.org/jdk/pull/17508#discussion_r1955837820
PR Review Comment: https://git.openjdk.org/jdk/pull/17508#discussion_r1955849996


More information about the hotspot-compiler-dev mailing list