RFR: 8315066: Add unsigned bounds and known bits to TypeInt/Long [v59]
Emanuel Peter
epeter at openjdk.org
Fri May 2 15:37:09 UTC 2025
On Fri, 2 May 2025 14:23:07 GMT, Emanuel Peter <epeter at openjdk.org> wrote:
>> Quan Anh Mai has updated the pull request incrementally with one additional commit since the last revision:
>>
>> add some more sanity static_asserts
>
> src/hotspot/share/opto/rangeinference.cpp line 338:
>
>> 336: // of i would violate 3.1 since lo[first_violation] does not satisfy bits.
>> 337: // As a result, we should find the last i upto first_violation such that
>> 338: // lo[i] == zeros[i] == 0.
>
> Excellent, this really sets up the bit tricks below! Nice 😊
Let's try to match the wording below to this, so it is clear that we are working towards this.
> src/hotspot/share/opto/rangeinference.cpp line 370:
>
>> 368: // bits. We will expand the implication of such cases below.
>> 369: // 0 1 1 0 0 0 0 0
>> 370: U tmp = ~either & find_mask;
>
> Suggestion:
>
> // In tmp exactly those bits are set that are upto first_violation and where
> // lo[i] == zeros[i] == 0. Hence: The last one of these bits is at bit index i.
> // Note that there may not exist such bits, i.e. tmp == 0. Hence we cannot
> // find any i that satisfies (3.1-3.3), and so there is no value not less than
> // lo that satisfies bits. We will expand the implication of such cases below.
> // 0 1 1 0 0 0 0 0
> U tmp = ~either & find_mask;
That is the smaller suggestion, I have a larger one below.
> src/hotspot/share/opto/rangeinference.cpp line 370:
>
>> 368: // bits. We will expand the implication of such cases below.
>> 369: // 0 1 1 0 0 0 0 0
>> 370: U tmp = ~either & find_mask;
>
> Suggestion:
>
> // We want to find the last i upto first_violation such that lo[i] == zeros[i] == 0.
> // We start with all bits where lo[i] == zeros[i] == 0:
> // 0 1 1 0 0 0 0 1
> U lo_eq_zeros_eq_zero = ~(lo | bits._zeros).
> // Now let us find all the bit indices x upto first_violation such that
> // lo[x] == zeros[x] == 0. The last one of these bits must be at index i.
> // 0 1 1 0 0 0 0 0
> // Note that there may not exist such bits, i.e. tmp == 0. Hence we cannot
> // find any i that satisfies (3.1-3.3), and so there is no value not less than
> // lo that satisfies bits. We will expand the implication of such cases below.
> U alignment_candidates = lo_eq_zeros_eq_zero & find_mask;
The benefit here: we have more explicit names. And the wording matches a little closer to our goal above.
> src/hotspot/share/opto/rangeinference.cpp line 387:
>
>> 385: // - new_lo[i] = 1 (2.6)
>> 386: // - new_lo[x] = 0, for x > i (not yet 2.7)
>> 387: // 1 0 1 0 0 0 0 0
>
> That's a little misleading if there is no such `i`...
> In that case `alignment = 0`, and `-alignment = 0`, and so `new_lo = 0`... which is not exactly an overflow, but smaller than `lo`, so kinda an overflow ;)
Suggestion:
// similar to aligning lo upto alignment. Also similar to the above case,
// this computation cannot overflow.
// We now have:
// - new_lo[x] = lo[x], for 0 <= x < i (2.5)
// - new_lo[i] = 1 (2.6)
// - new_lo[x] = 0, for x > i (not yet 2.7)
// If there is no such candidate, and no such i, then new_lo = 0.
// 1 0 1 0 0 0 0 0
> src/hotspot/share/opto/rangeinference.cpp line 398:
>
>> 396: // This is the result we are looking for.
>> 397: // 1 0 1 0 0 0 1 1
>> 398: new_lo |= bits._ones;
>
> Now we should probably also split the cases with and without candidates.
> Suggestion:
>
> // Assume there was at least one candidate, and i is the index of the last one:
> // Then there exists no value x not larger than i such that
> // new_lo[x] == 0 and ones[x] == 1. This is because all bits of lo before i
> // should satisfy bits, and new_lo[i] == 1. As a result, doing
> // new_lo |= bits.ones will give us a value such that:
> // - new_lo[x] = lo[x], for 0 <= x < i (2.5)
> // - new_lo[i] = 1 (2.6)
> // - new_lo[x] = ones[x], for x > i (2.7)
> // This is the result r we are looking for.
> // 1 0 1 0 0 0 1 1
> // If there was no candidate, then above we had new_lo = 0, and the
> // computation below gives us new_lo = ones.
> new_lo |= bits._ones;
The "no candidate" case should now have an argument why this is an ok value to return.
It does satisfy bits, since `ones` satisfy bits.
But do we know that `ones < lo`? We need that to get the "overflow" we promised at the very top of the method.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/17508#discussion_r2071695189
PR Review Comment: https://git.openjdk.org/jdk/pull/17508#discussion_r2071706651
PR Review Comment: https://git.openjdk.org/jdk/pull/17508#discussion_r2071722541
PR Review Comment: https://git.openjdk.org/jdk/pull/17508#discussion_r2071763058
PR Review Comment: https://git.openjdk.org/jdk/pull/17508#discussion_r2071788373
More information about the hotspot-compiler-dev
mailing list