RFR: 8373999: C2: apply KnownBits and unsigned bounds to Add / Sub operations [v4]

Benoît Maillard bmaillard at openjdk.org
Thu Jan 15 08:32:53 UTC 2026


On Wed, 14 Jan 2026 13:40:22 GMT, Quan Anh Mai <qamai at openjdk.org> wrote:

>> src/hotspot/share/opto/rangeinference.hpp line 437:
>> 
>>> 435:         // non-negative, the signed addition does not overflow, we can compute it directly.
>>> 436:         lo = S<CTP>(st1._ulo + st2._ulo);
>>> 437:         hi = S<CTP>(st1._uhi + st2._uhi);
>> 
>> Why not use the signed bounds directly since they are equal anyway? I find it a bit easier to read, and we can avoid the cast.
>> Suggestion:
>> 
>>         lo = st1._lo + st2._lo;
>>         hi = st1._hi + st2._hi;
>
> It is because `st1._lo` can be a 3-bit signed `int`. And I don't want to implement arithmetic for these signed classes since normally signed arithmetic is UB in the presence of overflow. And it seems not a good idea to either introduce UB for `int3_t` addition, or have inconsistent behaviour between things we test with and things that are the real guys.

Oh right, I didn't think of that, sorry. Thanks for explaining.

>> src/hotspot/share/opto/rangeinference.hpp line 453:
>> 
>>> 451:       //   sum[i] = bit & 1;
>>> 452:       //   carry[i - 1] = (bit >= 2);
>>> 453:       // }
>> 
>> Is there a specific reason why the notation here goes from `n-1` to `0` and not the reverse? I find it more intuitive to have index `0` for the least significant bit, but maybe there is some convention I am not aware of. It does not matter too much in any case, so feel free to do whatever.
>
> Since we are viewing the binary number as a bit string, I tend to think that it is more intuitive to imagine a value 0b1011 as a bit string "1011", which means the first index is the msb and the last index is the lsb. Normally, when I do Maths I use 0 as the lsb, though, since numbers are unbounded. But for this presentation, I think doing it this way is easier for the others to conceptualize.

Right, why not.

>> src/hotspot/share/opto/rangeinference.hpp line 480:
>> 
>>> 478:       //
>>> 479:       // If we gather the min_bits into a value tmp, it is clear that
>>> 480:       // tmp = st1._bits._ones + st2._bits._ones:
>> 
>> It feels like we don't need to "initialize" `tmp`, but maybe I am missing something
>
> This is not an initialization, though. This section just describes that a `tmp` constructed using the loop below is the same as the one constructed by adding these 2 values.

Oh I see, makes sense now. I think I was just confused about whether this was pseudo c++ or a mathematical expression.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/28897#discussion_r2693426631
PR Review Comment: https://git.openjdk.org/jdk/pull/28897#discussion_r2693424670
PR Review Comment: https://git.openjdk.org/jdk/pull/28897#discussion_r2693422440


More information about the hotspot-compiler-dev mailing list