RFR: 8240615: is_power_of_2() has Undefined Behaviour and is inconsistent
Andrew Haley
aph at redhat.com
Sat Mar 7 10:54:32 UTC 2020
On 3/6/20 7:48 PM, John Rose wrote:
> On Mar 6, 2020, at 9:11 AM, Andrew Haley <aph at redhat.com> wrote:
>>
>> + predicate(is_power_of_2((julong)n->get_long()));
>
> To me this is an easy “yes”. The hardware instruction in question
> uses the unsigned convention.
>
> The harder part is (as you say) figuring out where we were implicitly
> relying on unsigned conventions and behavior will change. But I
> think we’ve had plenty of eyeballs on this, and it’s easy to fix more
> stuff like this if we find it later, right?
I think we'll have to do that.
For the record:
This is a Hard Problem, for a reason that is not obvious.
In C2, you often have patterns like this:
match(If cmp (CmpI (AndI op1 op2) op3));
predicate(is_power_of_2(n->in(2)->in(1)->in(2)->get_int()));
...
ins_encode %{
...
int bit = exact_log2($op2$$constant);
Very unfortunately, (n->in(2)->in(1)->in(2)->get_int()) is a jint, but
$op2$$constant is an intptr_t. This is problematic if we're running on
a 64-bit machine because intptr_t is signed long.
At first I wanted to define exact_log2() and is_power_of_2() in a way
that treats all arguments as unsigned -- I wrote a patch which does
that -- but it doesn't help. Because of the above, even with a jint
operand representing 0x8000_0000, $op2$$constant returns
0xffff_ffff_8000_0000. This is a historic mistake in the design of C2,
IMO, but very hard to fix today.
So, AFAICS the only way to fix this is to treat all negative integer
values, whatever their size, as non-powers of 2.
--
Andrew Haley (he/him)
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
https://keybase.io/andrewhaley
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671
More information about the hotspot-runtime-dev
mailing list